Adi,你在这个例子中做的有两个问题。
第一个问题是,在立即调用函数内部,this === window
。
第二个问题是这些都是函数表达式。因此,它们都是在行内定义的。
function makeIt () {
this.a = function () { this.b(); };
this.b = function () { console.log("B"); };
}
这将会起作用,因为使用了后期静态绑定。
这意味着在
a
中,在函数被调用之前,浏览器不知道
this
代表什么。随后它会在那一时刻找到
this
所代表的对象。
否则,这就像分配变量一样:
function makeIt () {
this.a = this.b;
this.b = "George";
}
你会遇到一个错误。
为什么?因为在你赋值给a
的时候,b
还没有一个值。
function Foo () {
this.init = (function (context) { context.change(); }(this));
this.change = function () { doStuff(); };
}
那么这个语句有什么问题呢?嗯,立即调用函数就是立即调用的函数。这意味着,尽管我们通过将 this 的值作为参数传递到内部作用域中解决了 this 问题...但我们要求它运行尚不存在的内容。
function Foo () {
this.change = function () { doStuff(); };
this.init = (function (context) { context.change(); }(this));
}
这应该可以正常工作。
...然而...
...你为什么要这样做呢?
也就是说,当你想让它自动构建时,为什么要给它一个public
init
属性(它是undefined
)?
为什么init
是undefined
?因为你没有返回任何东西——你正在运行一个函数并将init
设置为函数的返回值,但它并没有返回任何东西,所以它将init
设置为undefined
。那为什么还要有init
呢?
两个解决方案:
function Foo () {
this.change = function () { doStuff(); };
var init = function () { this.change(); };
init();
}
或者:
function Foo () {
this.change = function () { doStuff(); };
(function (context) {
context.change();
}(this));
}
说实话,如果init
是私有的,并且自动运行,那么create
是否真的需要公开?
在已经创建了对象后,您是否会调用myObj.create();
?
为什么不这样做:
function Foo () {
this.public1 = "Bob";
this.public2 = 32;
this.publicMethod = function () {};
var create = function () { };
create();
}
或者,如果你不仅仅是在创建:create
:
function Foo () {
this.public1 = "Bob";
this.public2 = 32;
this.arrayOfThings = [];
this.publicMethod = function () {};
var create = function () {},
overclock = function () {},
polish = function () {};
(function (context) {
var thing;
for () {
thing = create();
polish(thing);
context.arrayOfThings.push(thing);
}
overclock(context.arrayOfThings);
}(this));
}
现在,你已经将所有的函数、属性和变量都放在了一个作用域中,并将初始化放在了另一个作用域中——所有设置逻辑都与最终对象的逻辑分离开来......而且你可以根据输入参数对对象进行分支处理(例如多态构造函数,它会基于输入修改其输出,同时保持相同的接口——或者是自包含工厂模式,其中所有蓝图都是100%私有和封闭的),而不会让实际赋值看起来像 ifs 和 fors 的混乱。
你不必在完成的对象之外调用设置(这意味着没有其他人能够调用已完成对象上的设置,以重新创建或重置它)。而所有这些只需要使用一个匿名函数,在this.init上使用即可。