gpt4 book ai didi

javascript - OO javascript - 构造函数中自执行函数的上下文/范围

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:20:08 24 4
gpt4 key购买 nike

在构造函数中使用自执行匿名函数时,我有一个关于上下文/范围的快速问题。

观察以下工作代码:

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 在全局意义上不存在。

我想我必须通过 call/apply 做一些事情,但我不确定具体是什么或在哪里。

如有任何指点,我们将不胜感激。

干杯,广告。

最佳答案

Adi,你在示例中所做的有两个问题。第一个问题是在立即调用的函数内部,this === window

第二个问题是这些都是函数表达式。因此,它们都是在线定义的。

function makeIt () {
this.a = function () { this.b(); };
this.b = function () { console.log("B"); };
}

由于后期静态绑定(bind),这将起作用。这意味着在 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 设置为函数的返回值,但它没有返回任何东西,所以它设置了 initundefined。那为什么要有 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 是私有(private)的,并且自动运行,那么 create 真的需要公开吗?您要在创建后调用 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));
}

现在,您已经在一个作用域中获得了所有函数、属性和变量,并且在另一个作用域中获得了初始化——所有设置逻辑都与最终对象的逻辑分离...。 ..你可以做一些事情,比如根据输入参数分支你的对象(比如多态构造函数,它会根据它得到的东西修改它给你的东西,同时保持相同的接口(interface) - 或者一个独立的工厂模式,其中所有蓝图都是 100% 私有(private)和封闭的),而不会使实际分配看起来像一团乱七八糟的 ifs 和 fors。

您不必在已完成对象之外调用设置(这意味着没有其他人可以调用已完成对象的设置来重新创建它/重置它)。无论如何,它所花费的只是一个匿名函数,您将在 this.init 上使用它。

关于javascript - OO javascript - 构造函数中自执行函数的上下文/范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12055282/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com