如何在JavaScript对象{}中不使用“this”

how would one not use `this` in a JavaScript object {}?

本文关键字:this JavaScript 对象      更新时间:2023-09-26

今年在挪威,Doug Crawford宣布他不再在JavaScript中使用this(或者他指的是ES6?)。真诚地,一个人怎么会不在这里使用this

var indexViewModel = {
    currentIndex: ko.observable(0),
    currentPage: ko.observable(1),
    displayItems: ko.observableArray(),
    indexSegmentsForPeople: [
        { id: "poetryinxhtml", text: "Poetry in XHTML5" },
        { id: "poetryinpdf", text: "Poetry in PDF" },
        { id: "poetryinstreams", text: "Poetry in Streams" },
        { id: "digitizedart", text: "Digitized Art" }
    ],
    indexSegmentsForTime: [
        { id: "prose", text: "Prose" },
        { id: "interviewsanddocumentary", text: "Interviews/Documentary" },
        { id: "therasxcontext", text: "the rasx() context" }
    ],
    indexVisitorLinks: [
        { url: "./rasx01.html", title: "about the kinté space" },
        { url: "./kfaqs.html", title: "kinté FAQs" },
        { url: "./khits.html", title: "kinté hits" },
        { url: "./rasx00.html", title: "the kinté space oddity" }
    ],
    items: [],
    itemsCount: ko.observable(0),
    itemsPerPage: 9,
    pageCount: ko.observable(0),
    getCurrentIndex: function () {
        return ((this.currentPage() - 1) * this.itemsPerPage);
    },
    getJSON: function (id) {
        var url = this.getIndexJsonUrl(id);
        var that = this;
        return $.getJSON(url).then(function (data) {
            that.setItems(data);
        });
    },
    getJSONforVisitors: function () {
        var that = this;
        return $.getJSON('./data/VisitorThumbs.json').then(function (data) {
            that.setItemsForVisitors(data);
        });
    },
    getIndexJsonUrl: function (id) {
        return './data/index-' + id + '.json';
    },
    getIsNewValue: function (pubDate) {
        var now = new Date();
        var test1 = ((now.getMonth() - pubDate.getMonth()) <= 2);
        var test2 = (pubDate.getFullYear() === now.getFullYear());
        return (test1 && test2);
    },
    getSlice: function () {
        return this.items.slice(this.currentIndex(),
                (this.currentIndex() + this.itemsPerPage));
    },
    isNextPageEnabled: ko.observable(true),
    isPreviousPageEnabled: ko.observable(false),
    setDisplayItems: function () {
        var that = this;
        var slice = this.getSlice();
        this.displayItems.remove(function (item) { return item; });
        _(slice).each(function (item) { that.displayItems.push(item); });
    },
    setEnabled: function () {
        this.isNextPageEnabled(this.currentPage() < this.pageCount());
        this.isPreviousPageEnabled(this.currentPage() > 1);
    },
    setItems: function (data) {
        var that = this;
        this.items = _(data.ChildDocuments)
            .sortBy(function (d) { return $.rx.dateTime.getJsonDate(d.CreateDate); }).reverse();
        _(this.items).each(function (item) {
            //Add .isNew property:
            var pubDate = $.rx.dateTime.getJsonDate(item.CreateDate);
            item.isNew = that.getIsNewValue(pubDate);
        });
        this.currentIndex(0);
        this.currentPage(1);
        this.itemsCount(this.items.length);
        this.pageCount(Math.ceil(this.itemsCount() / this.itemsPerPage));
        this.setDisplayItems();
        this.setEnabled();
    },
    setItemsForVisitors: function (data) {
        this.items = data.ChildDocuments;
        this.currentIndex(0);
        this.currentPage(1);
        this.itemsCount(this.items.length);
        this.pageCount(Math.ceil(this.itemsCount() / this.itemsPerPage));
        this.setDisplayItems();
        this.setEnabled();
    },
    setNextPage: function () {
        this.currentPage(this.currentPage() + 1);
        this.setEnabled();
        if (this.currentPage() > this.pageCount()) { this.currentPage(this.pageCount()); }
        this.currentIndex(this.getCurrentIndex());
        this.setDisplayItems();
    },
    setNextPageClickGate: function () {
        if (this.isNextPageEnabled()) { this.setNextPage(); } else { return false; }
    },
    setPreviousPage: function () {
        this.currentPage(this.currentPage() - 1);
        this.setEnabled();
        if (this.currentPage() < 1) { this.currentPage(1); }
        this.currentIndex(this.getCurrentIndex());
        this.setDisplayItems();
    },
    setPreviousPageClickGate: function () {
        if (this.isPreviousPageEnabled()) { this.setPreviousPage(); } else { return false; }
    },
    triggerAfterAdd: function (item, iterator) {
        $(window.document).trigger('afterAdd',
            ['IndexFlowTemplate', item, iterator]);
    }
};

你的代码片段对我来说并不是特别地道。它更像是直接翻译成Javascript的Java代码。在JS中,通常的"代码单元"(代码+数据)是一个闭包,而不是对象:

var indexViewModel = (function() {
    var
        currentIndex = ko.observable(0),
        currentPage = ko.observable(1),
        etc...
    function getCurrentIndex() {
        return (currentPage() - 1) * itemsPerPage;
    };
    function getJSON(id) {
        var url = getIndexJsonUrl(id);
        return $.getJSON(url).then(function (data) {
            setItems(data);
        });
    };
    etc....
    return {
        // whatever needs to be public
    };
})();

基本上,所有的"对象成员"都变成了局部变量,而"私有方法"=局部函数。正如您所看到的,根本不需要this(更不用说that=this)。代码更简单、更干净。

不确定你在问什么?克罗克福德不会写这样的代码。他的代码根本不使用this。这是一个设计问题——我的意思是,当然,你可以采用传统的面向对象风格编写的代码,去掉this,但你会弄得一团糟。你必须重新设计整个东西。

Crockford简单地将所有方法调用视为函数调用;没有接收器,只有传入的参数。对象被视为散列,它们的属性只能从外部访问。如果一段代码需要引用私有值,它会在局部变量上使用闭包。

不,这与ES6无关。除了隐式对象属性初始化之类的一些小便利之外,ES6在编码方式上似乎唯一改变的是,他将使用尾部递归来消除循环。