我已经全局定义了以下模块:
var module = (function () {
console.log(this);
this.fn = function () {
console.log(this);
}
return this;
})();
http://www.quirksmode.org/js/this.html:
In JavaScript |this| always refers to the “owner” of the function we're executing, or rather, to the object that a function is a method of.
对console.log
的第一个调用将Window
记录为this
的值,我理解这一点。但是,对console.log
的第二次调用也是如此。
既然this
指的是函数的所有者,为什么module.fn
记录Window
而不是module
?
当我调用fn
时,我仍然要写module.fn
,我不能写Window.fn
。由于this
指的是Window
,我觉得这很令人困惑。
编辑:在我的示例中,我忘记返回this
。
既然这是指函数的所有者,为什么module.fn记录窗口而不是模块?
外部函数的返回值是window
,因为它在任何特定的上下文中都不会被调用,所以module
最终也是window
。
您应用模块模式的方式似乎是错误的。它应该返回在代码的其余部分中使用的公共接口:
var module = (function () {
console.log(this);
// public interface
return {
fn: function () {
console.log(this);
}
}
})();
module.fn(); // "Object {fn: function}"
在您的示例中,全局对象接收fn
。在浏览器的情况下,它是window
对象。这是因为在没有特定上下文的情况下调用函数(有效地构建了一个新的作用域)。最后,module
对象只是对window
的引用(因为return this;
)。
什么是this
在JavaScript中,this
是当前上下文,即在特定时间调用函数的对象。它不是函数的"持有者"。您总是可以从其他对象中"窃取"该方法,并将其apply
(字面上)保存到自己的对象中。
假设您出于某种原因想要对arguments
对象进行切片。它看起来就像一个数组,但它不是一个数组。arguments.slice(2,4)
不起作用(假设ECMAScript<5)。该怎么办?
Array.prototype.slice.apply(arguments, [2,4]);
您需要从Array原型中窃取slice
函数,并在参数中使用if。在slice
调用中,"this"是特定时间的arguments对象。
如何构造一个有效的模块
您的工作是return
模块对象。你不想弄乱上下文。只要您没有将函数直接应用于模块对象,它就不相关。
最简单的解决方案就是最简单的。
var module = (function() {
// do something internally, great for "private" stuff
// then return the "public" interface
return {
doSomething: function() {
// do something
},
introduce: function() {
console.log(this);
}
};
})();
module.introduce(); // Object {doSomething: function, introduce: function}
module.doSomething();
相反
或者,如果你真的想的话,你可以使用this
来完成你的工作,使用apply
var module = {};
(function(){
this.doSomething = function() {
// do something
};
this.introduce = function() {
console.log(this);
};
}).apply(module);
module.introduce(); // Object {doSomething: function, introduce: function}
module.doSomething();
请注意,这几乎等于"新"调用。
有更多同样有效的方法可以做到这一点,但第一种方法经常使用,而且非常清晰。无论如何,一切都取决于您的代码约定。
您的模式是错误的,您正在做的是创建一个封闭的作用域,并将module
设置为该作用域的返回值:
// This is the design pattern:
var module = (function () {
var module = {};
var localVar = 1;
module.moduleVar = 2;
module.fn = function () {
console.log(this);
}
return module;
})();
console.log(module.fn); // function() { console.log(this) ;}
console.log(module.moduleVar); // 2
console.log(module.localVar); // undefined