ES6类字面量中的IIFE

7
在ES5中,我们都可以这样做:
myClass.prototype.myMethod = (function () {return function() {}})();

我能否使用ES6类字面量实现同样的技巧?


请展示一下使用类字面量的例子。 - zzzzBov
5个回答

12

不,目前还不支持。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() })()

2
你如何从构造函数中定义的this访问IIFE函数? - husnul

6

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
你的示例似乎可以工作,但是1.使用了箭头函数,2.从未使用this关键字。我第一次尝试使用普通函数表达式和this的用法失败了。与普通函数表达式不同,箭头函数继承了本地调用上下文。在这种情况下,这个上下文有点不清楚。我试图用.call(this)替换()调用,但没有帮助(这是什么?)。我会尝试弄清问题所在,但当然不能确定解决它。无论如何,这可能对于部署来说有点过于高科技,因为许多用户将拥有2019年之前的浏览器。 - Elias Hasle
抱歉,我的错。请看一下我的新答案(几分钟后)。 - Elias Hasle
2
它可能不使用 this,但是它可以。这并不是太高科技。这些赋值是在构造函数中完成的,不要害怕。就像你写的 constructor() {this.IIFE = ...} 一样。请参见 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Field_declarations。 - Ruan Mendes
感谢 constructor() {this.IIFE = ...},它提供了传递初始值的能力。 - Igor Fomenko
@JuanMendes 我已经查看了这个以及其他问题的类似解决方案(例如在此处),我想知道返回的箭头函数是否会充当隐式构造函数?您能否在该函数中定义属性? - DeltaFlyer

4

可以创建一个装饰器:

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

并像这样使用:

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

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


3
2019年@juanma-menendez的回答很有趣,但我还有一些疑问和未解答的问题。
首先,它使用箭头函数。箭头函数处理调用上下文的方式与普通函数表达式不同。此外,它们不支持递归(据我所知)。
第二个问题是它从未尝试过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)是错误的。同时,我也有些困惑为什么私有数组会为每个实例创建,而不是仅存在于原型中。我不确定这是否等同于使用IIFE创建的原型方法。

无论如何,这对于部署可能过于高级,因为许多最终用户将使用2019年以前的浏览器。此外,我还没有测试性能。使用需谨慎! :-)


0

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接