天天看點

ES6 method寫法與TypeError: is not a constructor

公司前端最近開始強推ESlint,很多檔案需要逐漸修改為符合ESlint規則的形式。

結果遇到了一個神奇的問題,有一段類似這樣的代碼:

let obj = {
    init: function($el) {    // 此處ESlint檢查提示‘Expect method shorthand.(Object-shorthand)’
        this.$el = $el;
    }
};
obj.init.prototype = {
    log() { console.log(this); }
};
new obj.init('o');
           

因為eslintrc中

Object-shorthand

規則的設定,這種類内的函數成員要縮寫成ES6 的Method方式,也就是下面這樣:

let obj = {
    init($el) {    // 修改為Method形式,通過了ESlint檢查
        this.$el = $el;
    }
};
obj.init.prototype = {
    log() { console.log(this); }
};
new obj.init('o'); // TypeError: obj.init is not a constructor
           

這就讓人郁悶了,這都能報錯,這兩種寫法不是等價麼?接着進行了一些對比:

let obj = {
    init: function($el) {
        this.$el = $el;
    }
};
console.log(Object.getOwnPropertyNames(obj.init));// [ 'length', 'name', 'arguments', 'caller', 'prototype' ]
console.log(obj.init.prototype);// { log: [Function: log] }
obj.init.prototype = {
    log() { console.log(this); }
};
console.log(Object.getOwnPropertyNames(obj.init));// [ 'length', 'name', 'arguments', 'caller', 'prototype' ]
console.log(obj.init.prototype);// { log: [Function: log] }
new obj.init('o').log(); // { '$el': 'o' }
           
let obj = {
    init($el) {
        this.$el = $el;
    }
};
console.log(Object.getOwnPropertyNames(obj.init));// [ 'length', 'name' ]
console.log(obj.init.prototype);// undefined
obj.init.prototype = {
    log() { console.log(this); }
};
console.log(Object.getOwnPropertyNames(obj.init));// [ 'length', 'name', 'prototype' ]
console.log(obj.init.prototype);// { log: [Function: log] }
new obj.init('o').log();// TypeError: obj.init is not a constructor
           

對比結果成功颠覆了我一直以來的認知。ES6的Method竟然和一般的函數不一樣,不能作為構造函數來使用。

後來在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions此處找到了下面這一段:

ES6 method寫法與TypeError: is not a constructor

繼續閱讀