如何使 Immediately-Invoked-Func-Expression 在构造对象后立即访问 javascript 中先前定义的 属性

How to make a Immediately-Invoked-Func-Expression to have access to a previously defined property in javascript as soon as the object is constructed

 var Counter = function(name) {
    this.name = name;
    this.data = (function() {
        console.log(this.name);
    })();
};

var counter = new Counter("some name");

预期行为: 打印 "some name"。

当前行为:未打印任何内容。

我试图在构建对象后立即使用内部 属性 "data"。使用依赖于内部 属性 "name" 的函数检索此 "data"。但是,当立即调用的函数表达式被调用时,看起来它无法访问 this.name 属性,所以我无法在对象构造后立即检索我的数据。

我可以通过首先定义一个等价于 this 的方法使其工作,例如:

var Counter = function(name) {
    var that = {};
    that.name = name;
    that.data = (function() {
        console.log(that.name);
    })();
    return that;
};

var counter = new Counter("some name");

为什么会这样?我怎样才能让它以优雅的方式工作?

this is notorious in JavaScript for changing in different contexts。内部函数中的 this 是全局对象(window 如果你在浏览器中 运行 它),而不是构造函数中的 this 对象。

有几种不同的解决方案,具体取决于您所针对的 JavaScript 版本:

ECMAScript 5

您可以使用 apply[MDN]:

传递 this

var Counter = function(name) {
  this.name = name;
  this.data = (function() {
    console.log(this.name);
  }).apply(this);
};

var counter = new Counter("some name");

ECMAScript 6

If you are using ES6, you can use arrow functions,自动绑定父函数的this值:

var Counter = function(name) {
  this.name = name;
  this.data = (() => {
    console.log(this.name);
  })();
};

var counter = new Counter("some name");

ECMAScript 3

另一个选项,类似于您在问题中的选项,是将 this 分配给一个新变量 that。然后可以在子函数中引用that

var Counter = function(name) {
  var that = this;
  that.name = name;
  that.data = (function() {
    console.log(that.name);
  })();
};

var counter = new Counter("some name");

在 ECMAScript 5 中引入 apply 之前,这是最常见的解决方案。

你的例子中的问题是上下文。当使用 (function(){ } )() 时,你使用了一个新的上下文,它有 this.name 不同于 Counter 函数名 属性.

您可以使用箭头函数使上下文在您的 IIFE 函数中使用。


警告:我的解决方案需要 ECMA2015es6 支持。没有 es6 的另一个解决方案是使用@Peter Olson 答案。

Here可以看到箭头函数的兼容性table

const Counter = function(name) {
    this.name = name;
    
    this.data = (() => {
      console.log(this.name);
    })();
};

const counter = new Counter('some name');

以上是一些很好的信息。我也很好奇你是否可以只分配 this.data,然后立即调用你的函数?

var Counter = function(name) {
  this.name = name;
  this.data = this.name;
  console.log(this.data);
};

var counter = new Counter("some name");