Javascript模块模式,范围和“这个”

时间:2012-03-07 16:03:22

标签: javascript

我正试图围绕构建自定义JavaScript库。我已经阅读了很多关于模块模式的内容,还阅读了Crockford关于私人和公共成员的文章。我知道什么是立即调用的函数表达式以及我们为什么要这样做

var myLib = (function() {
}())

然而,在某些情况下,我仍然有点失去关于范围和关闭的一般情况。我遇到的具体问题是:

为什么以下示例会警告DOMWindow而不是myLib对象? http://jsfiddle.net/slavo/xNJtW/1/

如果您能够解释该示例中所有方法中“this”所指的内容以及原因,那就太棒了。

4 个答案:

答案 0 :(得分:4)

在声明的任何函数内(任何地方)并调用如下this将是窗口对象

function anyFunc(){
    alert(this);  // window object
}

anyFunc();


var anyFunc2 = function(){
    alert(this);  // window object
}

anyFunc2();

如果要创建私有函数并访问“myObject”实例,可以使用以下任一方法

module = (function () {

    var privateFunc = function() {
        alert(this);
    }

    var myObject = {
        publicMethod: function() {
            privateFunc.apply(this); // or privateFunc.call(this);
        }
    };

    return myObject;
}());


module.publicMethod();

两个

module = (function () {

    var _this; // proxy variable for instance

    var privateFunc = function() {
        alert(_this);
    }

    var myObject = {
        publicMethod: function() {
            privateFunc();
        }
    };
    _this = myObject;
    return myObject;
}());


module.publicMethod();

这些是您的问题的解决方案。我建议使用基于原型的对象。

编辑:

您可以使用第一种方法。

事实上,myObjectprivateFunc的范围相同,您可以直接在函数内使用

 var privateFunc = function() {
     alert(myObject);
 }

真实情况是你可以使用代理this如下所示。您也可以使用call

Module = function () {

    var _this; // proxy variable for instance

    var privateFunc = function() {
        alert(this + "," + _this);
    }

    this.publicMethod = function() {
        privateFunc(); // alerts [object Window],[object Object]
        privateFunc.call(this); // alerts [object Object],[object Object]
    }

    _this = this;
    return this;
};

var module = new Module();
module.publicMethod();

答案 1 :(得分:0)

您需要明确声明myPrivateMethod是myLib的成员:

function MyLib ()
{
    this._myPrivateField = "private";
    this._myPrivateMEthod = function ()
    { 
         alert(this); // Alerts MyLib function;
    }
}

var libObject = new MyLib();

请记住,如果不使用机箱技术,JavaScript中的任何内容都不会真正私密!

更好的方法就是这样:

function MyLib(instanceName)
{
    this.name = instanceName;
}

MyLib.prototype.myPrivateFunction()
{
    alert(this);
}

在此之后调用您的方法:

var libObject = new MyLib();
libObject.myPrivateMethod(); // Alerts info about libObject.

答案 2 :(得分:-1)

关于模块模式需要记住的是它运行一次并完成。仍然可以调用的方法是闭包。在创建模块时,“this”指向窗口并被其值替换。

答案 3 :(得分:-2)

在你的联系小提琴中,"这个"关键字永远不会被" new"关键字或其他上下文更改,因此它仍然引用全局窗口对象。

编辑:澄清