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(); };
// other stuff......
init();
}
或者:
function Foo () {
this.change = function () { doStuff(); };
// other stuff....
(function (context) {
context.change();
/* a bunch of other stuff that would be in init
if there was no other stuff, why not just call this.change()? */
}(this));
}
老实说,如果init
是私有的并自动运行,create
真的需要公开吗?你要myObj.create();
在它已经创建后打电话吗?
为什么不做类似的事情:
function Foo () {
this.public1 = "Bob";
this.public2 = 32;
this.publicMethod = function () {};
var create = function () { /* initialize here */ };
create();
}
或者,如果你做的不仅仅是create
:
function Foo () {
this.public1 = "Bob";
this.public2 = 32;
this.arrayOfThings = [];
this.publicMethod = function () {};
var create = function () {},
overclock = function () {},
polish = function () {};
// Initialize Everything
(function (context) {
var thing;
for (/* ... */) {
thing = create();
polish(thing);
context.arrayOfThings.push(thing);
}
overclock(context.arrayOfThings);
}(this));
}
现在,您已经在一个范围内获得了所有函数、属性和变量,并且在另一个范围内进行了初始化——所有设置逻辑都与最终对象的逻辑分开......你可以做一些事情,比如根据输入参数分支你的对象(比如多态构造函数,它会根据它得到的东西修改它给你的东西,同时保持相同的接口——或者一个自包含的工厂模式,其中所有蓝图都是100% 私密和封闭),不会让实际作业看起来像一堆 if 和 fors。
您不必在已完成的对象之外调用设置(这意味着没有其他人可以在已完成的对象上调用设置,以重新创建/重置它)。this.init
它所花费的只是一个你无论如何都要使用的匿名函数。