首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >这种定义JS对象的方式有什么用处吗?

这种定义JS对象的方式有什么用处吗?
EN

Stack Overflow用户
提问于 2014-11-07 04:02:30
回答 3查看 3.2K关注 0票数 87

我正在维护一些遗留代码,并注意到使用了以下定义对象的模式:

var MyObject = {};

(function (root) {

    root.myFunction = function (foo) {
        //do something
    };

})(MyObject);

这样做有什么目的吗?它是否等同于只执行以下操作?

var MyObject = {

    myFunction : function (foo) {
        //do something
    };

};

我并不打算按照自己的喜好去重构整个代码库,但我真的很想了解这种拐弯抹角的定义对象方式背后的原因。

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-11-07 04:05:29

它被称为模块模式http://toddmotto.com/mastering-the-module-pattern/

主要原因是您需要创建真正私有的方法和变量。在您的例子中,它没有任何意义,因为它没有隐藏任何实现细节。

这里有一个使用模块模式有意义的例子。

var MyNameSpace = {};

(function(ns){
    // The value variable is hidden from the outside world
    var value = 0;

    // So is this function
    function adder(num) {
       return num + 1;
    }

    ns.getNext = function () {
       return value = adder(value);
    }
})(MyNameSpace);

var id = MyNameSpace.getNext(); // 1
var otherId = MyNameSpace.getNext(); // 2
var otherId = MyNameSpace.getNext(); // 3

而如果你仅仅使用一个普通的对象,addervalue就会变成公共的

var MyNameSpace = {
    value: 0,
    adder: function(num) {
       return num + 1;
    },
    getNext: function() {
       return this.value = this.adder(this.value);
    }
}

你可以通过做像这样的事情来打破它

MyNameSpace.getNext(); // 1
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 1 again
delete MyNameSpace.adder;
MyNameSpace.getNext(); // error undefined is not a function

而是使用模块版本

MyNameSpace.getNext(); // 1
 // Is not affecting the internal value, it's creating a new property
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 2, yessss
// Is not deleting anything
delete MyNameSpace.adder;
MyNameSpace.getNext(); // no problemo, outputs 3
票数 116
EN

Stack Overflow用户

发布于 2014-11-07 04:24:08

在您所展示的特定情况下,在功能或可见性方面没有任何有意义的区别。

最初的程序员很可能采用这种方法作为一种模板,允许他定义私有变量,这些变量可以在定义myFunction之类的东西时使用

var MyObject = {};
(function(root) {
    var seconds_per_day = 24 * 60 * 60;   // <-- private variable
    root.myFunction = function(foo) {
        return seconds_per_day;
    };
})(MyObject);

这避免了每次调用函数时都计算seconds_per_day,同时也避免了它污染全局作用域。

然而,这并没有什么本质上的区别,只是说

var MyObject = function() {
    var seconds_per_day = 24 * 60 * 60;
    return {
        myFunction: function(foo) {
            return seconds_per_day;
        }
    };
}();

原始编码器可能更希望能够使用root.myFunction = function的声明性语法而不是myFunction: function的对象/属性语法向对象添加函数。但这种差异主要是偏好问题。

然而,原始编码器采用的结构有一个优点,即可以很容易地在代码中的其他地方添加属性/方法:

var MyObject = {};
(function(root) {
    var seconds_per_day = 24 * 60 * 60;
    root.myFunction = function(foo) {
        return seconds_per_day;
    };
})(MyObject);

(function(root) {
    var another_private_variable = Math.pi;
    root.myFunction2 = function(bar) { };
})(MyObject);

归根结底,如果你不需要的话,就没有必要采用这种方法,但也没有必要改变它,因为它工作得很好,而且实际上有一些优点。

票数 6
EN

Stack Overflow用户

发布于 2014-11-07 04:14:34

此模式提供了一个作用域,您可以在其中定义在全局作用域中不可见的助手函数:

(function (root) {

    function doFoo() { ... };

    root.myFunction = function (foo) {
        //do something
        doFoo();
        //do something else
    };

})(MyObject);

doFoo是匿名函数的本地函数,不能从外部引用它。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26788397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档