一篇就夠-JS的new實現(xiàn)

new的作用

function Fruit(name){
    this.name = name;
}
Fruit.prototype.show = function(){
    console.log(this.name);
}

var banana = new Fruit('banana');
//輸出Fruit.protoype
console.log(Object.getPrototypeOf(banana));
//輸出Fruit.prototype
console.log(banana.__proto__);
//輸出'banana'
console.log(banana.show());
//輸出'banana'
console.log(banana.name);
//輸出true
console.log(banana.hasOwnProperty("name"));
//輸出false
console.log(banana.hasOwnProperty("show"));

可以看到,經(jīng)過new之后返回了一個對象,該對象的構(gòu)造函數(shù)原型為Fruit.prototype,也就是proto指向Fruit.prototype
并且banana可以調(diào)用show和name屬性,但name是其擁有的屬性,show是原型上的屬性。
也就是new做了以下幾件事

  • 返回一個對象,該對象的proto指向構(gòu)造函數(shù)的原型
  • 該對象會實現(xiàn)構(gòu)造函數(shù)中的實例屬性,也就是調(diào)用構(gòu)造函數(shù)的apply方法

初步實現(xiàn)new操作符

function objectFactory(paramConstrutor){
    if(typeof paramConstrutor !== 'function' ){
        throw new Error("");
    }
    var args = Array.prototype.slice.call(arguments,1);
    //設(shè)置obj的proto為constructor的proto,也就是繼承共享屬性
    //兩種方式,
    //一種是直接設(shè)置__proto__,官方不建議,后面可能變成只讀屬性
    var obj = new Object();
    obj.__proto__ = paramConstrutor.prototype;
    //一種是通過Object.create()或者該方式的polyfill
    //模擬Object.create()
    function Empty(){};
    Empty.prototype = paramConstructor.prototype;
    var obj = new Empty();
    //繼承實例屬性
    paramConstructor.apply(obj,args);
    return obj;
}

如果構(gòu)造函數(shù)由返回值,那應(yīng)該是返回新建的對象還是返回值呢?

  • 直接返回返回值,當(dāng)返回值是Object、Function、Array、Date、RegExg、Error
  • 返回新建對象,當(dāng)返回值是Null、Undefined、Number、Boolean、String、Symbol
function Fruit(name){
    this.name = name;
    return {
        a:1
    }
}

var banana = new Fruit('banana');
//{a:1}
console.log(banana);
function Fruit(name){
    this.name = name;
    return 1;
}

var banana = new Fruit('banana');
//Fruit {name:'banana‘}
console.log(banana);

完整代碼

根據(jù)上面的返回值,進(jìn)一步完善代碼。
需要了解的:

  • typeof檢測除了Function之外的都為object
  • typeof檢測Null為object
function objectFactory(paramConstructor){
    if(typeof paramConstructor !== 'function'){
        throw new Error("");
    }
    var args = Array.prototype.slice.call(arguments,1);
    //繼承共享屬性,修改proto屬性
    function Empty(){};
    Empty.prototype = paramConstructor.prototype;
    var obj = new Empty();
    //繼承實例屬性
    var result = paramConstructor.apply(obj,args);
    var isObejct = typeof result === 'object' && result !== null;
    var isFunction = typeof result === 'function';
    if(isObejct ||isFunction ){
        return result
    }
    return obj;
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容