【问题标题】:IIFE in ES6 class literalES6 类文字中的 IIFE
【发布时间】:2016-09-02 16:45:43
【问题描述】:

在 ES5 中我们都可以这样做:

myClass.prototype.myMethod = (function () {return function() {}})();

我能用 ES6 类文字做同样的把戏吗?

【问题讨论】:

  • 请用类文字举例说明您所指的内容。

标签: javascript ecmascript-6


【解决方案1】:

不,至少现在还没有。 ES6 类只支持声明方法,因此任何不是直接方法的东西(包括间接评估为方法的东西,例如 IIFE)仍然必须使用原型声明。

然而,ES6 类的工作方式与 ES5 构造函数的工作方式相同,只是语法更简洁,所以你仍然可以这样做:

class MyClass {
  constructor() {
    /* initialize */
  }

  regularMethod() {
    /* some stuff */
  }
}

MyClass.prototype.myMethod = (function() { return function() })()

相当于这个:

function MyClass() {
  /* initialize */
}

MyClass.prototype.regularMethod = function() {
  /* some stuff */
}

MyClass.prototype.myMethod = (function() { return function() })()

【讨论】:

  • 如何从 IIFE 函数访问构造函数中定义的this
【解决方案2】:

2019 年更新


是的,你可以做到。

您只需要像“函数表达式”一样创建 IIFE(将其分配给变量)

class MyClass {

  IIFE = (() => {

    let textArrayCreatedJustOnce = ['text A', 'text B', 'text C'];
    console.log('Only called in object creation');


    return () => {
      console.log(textArrayCreatedJustOnce[1]);
    }

  })()

}


let myClassInstance = new MyClass(); //log: 'Only called in object creation' 


myClassInstance.IIFE(); //log: 'text B'
myClassInstance.IIFE(); //log: 'text B'
myClassInstance.IIFE(); //log: 'text B'

【讨论】:

  • 您的示例似乎有效,但是 1. 使用箭头函数和 2. 从不使用 this 关键字。我第一次尝试使用通用函数表达式并使用它失败了。与普通函数表达式不同,箭头函数继承本地调用上下文。不过,在这种情况下,这种情况是什么还不清楚。我试图用 .call(this) 替换 () 调用,但它没有帮助(这是什么?)。我会尝试找出问题所在,但我当然不确定解决它。无论如何,这对于部署来说可能有点太高科技了,因为许多用户将使用 2019 年之前的浏览器。
  • 对不起,我的错。查看我的新答案(几分钟后)。
  • 它可能不会使用this,但可以。这不是太高科技。这些分配是在构造函数中完成的,不要害怕。就好像你写了constructor() {this.IIFE = ...}developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 感谢 constructor() {this.IIFE = ...} 它提供了传递初始值的能力
  • @JuanMendes 我已经看过这个以及其他问题的类似解决方案(例如here),我想知道返回的箭头函数是否会充当隐式构造函数?你会在那个函数中定义属性吗?
【解决方案3】:

可以创建一个装饰器:

function iife(target, key, { value: fn, configurable, enumerable }) {
  return {
    configurable,
    enumerable,
    value: fn(),
  };
}

并像这样使用它:

class MyClass {
  @iife
  methodName() {
    /* some stuff */
    return function() {
      /* real method content */
    }
  }
}

如果我需要一些繁重的临时变量,例如我不想为每个方法调用创建的向量矩阵,我会使用它。

【讨论】:

    【解决方案4】:

    @juanma-menendez 的 2019 年回答很有趣,尽管给我留下了一些疑问和未回答的问题。

    第一个问题是它使用了箭头函数。箭头函数处理调用上下文的方式与普通函数表达式不同。此外,它们不支持递归(据我所知)。

    第二个问题是它从不尝试this 关键字。

    在这个句法糖浆中调用上下文是什么有点不清楚。

    经过一些不成功的尝试,我在 Google Chrome 中成功进行了以下设置。此示例演示了可以从返回的方法访问私有属性和对象属性,并且它适用于多个实例:

    class C {
        constructor(attr) {
            this.attr = attr;
        }
        IIFE = function() {
            const privateArray = ["A", "B", "C"];
            console.log("Created private array during object creation.");
    
            return function() {
                console.log("privateArray[1] = %s", privateArray[1]);
                console.log("this.attr = ", this.attr);
            }//.bind(this);
        }.call(this);
    }
    
    var obj1 = new C("asdf");
    console.log(obj1.IIFE());
    console.log(obj1.IIFE());
    var obj2 = new C("ghjk");
    console.log(obj2.IIFE());
    

    输出(未定义为返回值):

    Created private array during object creation.
    privateArray[1] = B
    this.attr =  asdf
    undefined
    privateArray[1] = B
    this.attr =  asdf
    undefined
    Created private array during object creation.
    privateArray[1] = B
    this.attr =  ghjk
    undefined
    

    我必须承认我不明白为什么.bind(this) 是错误的。我也有点困惑,私有数组是为每个实例创建的,并且不仅仅存在于原型中。我不是 100% 确定这是否等同于使用 IIFE 制作的原型方法。

    无论如何,这对于部署来说可能有点太高科技了,因为许多最终用户将使用 2019 年之前的浏览器。另外,我还没有测试过性能。使用风险自负! :-)

    【讨论】:

      【解决方案5】:

      不,类文字不能包含 IIFE,它们需要由方法声明组成。

      在使用 class 关键字声明 myClass 之后,您可以在 ES6 中使用相同的赋值。然而,在 ES6 中使用 IIFE 并没有什么好的理由,因为它们通常可以被块作用域或模块替换。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-21
        • 2021-01-06
        • 1970-01-01
        • 2018-08-07
        • 2020-09-05
        • 1970-01-01
        相关资源
        最近更新 更多