简体   繁体   中英

IIFE in ES6 class literal

In ES5 we all could do like this:

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

Am I able to do the same trick with ES6 class literals?

No, not yet at least. ES6 classes only have support for declaring methods, so anything that's not directly a method (this includes things that indirectly evaluate to a method, such as IIFE) must still be declared with the prototype.

However, ES6 classes really work the same as ES5 constructor functions do, only with a bit cleaner syntax, so you can still do this:

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

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

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

which would be equivalent to this:

function MyClass() {
  /* initialize */
}

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

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

It's possible to crate a decorator:

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

And use it like:

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

I use it if I need some heavy temporary variables like matrices of vectors that I don't want to crate for each method call.


2019 UPDATE


YES , you can do it.

You just need to create the IIFE like a "function expression" (assign it to a variable)

 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' 

The 2019 answer from @juanma-menendez is interesting, although I was left with some doubts and unanswered questions.

The first problem is that it uses arrow functions. Arrow functions handle calling context differently than ordinary function expressions. Also, they don't support recursion (as far as I know).

The second problem is that it never tries the this keyword.

It is somewhat unclear what the calling context is in this syntactic syrup.

After some unsuccessful tries, I succeeded with the following setup in Google Chrome. This example demonstrates that both private and object attributes can be accessed from the returned method, and that it works with multiple instances:

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());

Outputs (undefined is the return value):

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

I must admit I don't understand why .bind(this) was wrong. I am also a bit confused that the private array is created for each instance, and does not live solely in the prototype. I am not 100% sure this is equivalent to a prototype method made with IIFE.

Anyway, this may all possibly be a bit too high-tech for deployment, as many end users will have pre-2019 browsers. Also, I have not tested the performance. Use at own risk! :-)

No, class literals cannot contain an IIFE, they need to consist of method declarations.

You can use the same assignment in ES6 though after having declared myClass using the class keyword. However there's not really any good reason to use IIFEs in ES6 at all, given they can usually be replaced by block scopes or modules.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM