在构造函数中使用自执行anon函数时,我有一个关于上下文/范围的快速问题.
请注意以下工作代码:
function Foo() {
this.height = 10;
this.width = 10;
this.init = function() {
this.create();
};
this.create = function() {
alert('test');
};
}
var span1 = new Foo();
span1.init();
警报显示为预测.但是,我不想在底部调用span1.init.我宁愿让Constructor函数中的init函数自动执行.这将给我如下代码:
function Foo() {
this.height = 10;
this.width = 10;
this.init = (function() {
this.create();
})();
this.create = function() {
alert('test');
};
}
var span1 = new Foo();
然而,在一些谷歌搜索后,似乎使用自我执行给它全球范围,因此this.create在全球意义上不存在.
我想我必须做一些电话/申请,但我不确定究竟是什么或在哪里.
任何指针都将非常感激.
干杯,
广告.
最佳答案 阿迪,你在这个例子中所做的事情有两个问题.
第一个问题是在立即调用的函数内部,这个===窗口.
第二个问题是这些都是函数表达式.
因此,它们都是在线定义的.
function makeIt () {
this.a = function () { this.b(); };
this.b = function () { console.log("B"); };
}
由于后期静态绑定,这将起作用.
这意味着在a内部,浏览器在调用函数之前不知道它指的是什么.然后它会在那个确切的时刻找到它所引用的对象.
否则,就像分配变量一样:
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的值作为参数传递给内部范围……
……我们要求它运行一些尚不存在的东西.
function Foo () {
this.change = function () { doStuff(); };
this.init = (function (context) { context.change(); }(this));
}
这应该工作得很好.
…然而…
…为什么你会这么做呢?
就像在,当你想要它自动构建时,你为什么要给它一个公共init属性(未定义)?
为什么init未定义?因为你没有返回任何东西 – 你正在运行一个函数并将init设置为函数的返回值,但是它没有返回任何东西,所以它将init设置为undefined.为什么要在那里初始化呢?
两种解决方案
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是私有的,并且自动运行,那么创建真的需要公开吗?
你打算叫myObj.create();在它已经被创建之后?
为什么不这样做:
function Foo () {
this.public1 = "Bob";
this.public2 = 32;
this.publicMethod = function () {};
var create = function () { /* initialize here */ };
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%私人和封闭的),没有使实际的任务看起来像一堆乱七八糟的.
您不必在完成的对象之外调用设置(这意味着没有其他人可以调用已完成的对象上的设置,重新创建它/重置它).而且所有成本都是你要在this.init上使用的一个匿名函数.