javascript new 的原理

昨晚看了一篇模擬實現 js new 的文章,今天覆盤一下

 

function a(){
    this.b = 'bb';
}
a.prototype.c = 'cc';

var aa = new a();

new 其實做了三件事情,首先它肯定是創建了一個對象

2.將 a 的prototype屬性對象通過引用傳遞賦值給 aa.__proto__ ,相當於:aa.__proto__ = a.prototype

進一步證實一下:

第三件事:用對象 aa 調用函數 a,從而使 a 內部的 this 指向 aa,即:

a.apply(aa)

 這樣 aa 就有了屬性 b

這樣我們就用上面的三步“生產”出了一個和 new 效果一樣的對象 bb;

 

以上就是 new 的基本原理了,但還有一些小細節 :

1. 函數a 如果有參數

2. 函數 a 如果有返回值

1 : 比較簡單,修改第三步爲 a.apply(bb , [arg1, arg2, ...])  就可以了

2 : 分兩種情況:

    a.返回值類型爲基本類型: string number null undefined boolean symbol 

    b.返回值爲對象 即,typeof 等於 'object' 或 'function' ,這裏麪包含了 Array、Date、RegExp、Error 等。。。

情況 a 是我們上面講的普通情況,

但是當我們 new 一個返回值爲對象的函數時,js 不會執行上面的那些操作,而是執行函數並返回函數的發回值 即:

new a();  和 a(); 的效果是一樣的:

 

所以如果要自己模擬一個 new 函數可以這樣寫:

function newOperator(ctor){
    if(typeof ctor !== 'function'){
      throw 'newOperator function the first param must be a function';
    }
    //es6 new.target 指向構造函數(這個沒有細究)
    newOperator.target = ctor;

    //這裏可以通過 Object.create 將第一二步合成一步
    var newObj = Object.create(ctor.prototype);
    var argsArr = [].slice.call(arguments);
    argsArr.shift();
    var ctorReturnResult = ctor.apply(newObj, argsArr);
    if(typeof ctorReturnResult === 'object' && ctorReturnResult !== null){
        return ctorReturnResult;
    }
    if(typeof ctorReturnResult === 'function'){
        return ctorReturnResult;
    }
    return newObj;
}

 

 

當然 js 也賦予了 prototype __proto__ 這些特殊屬性一些特殊作用,

比如 可以用 aa.c  來訪問 aa.__proto__.c  前提是 aa 沒有 c 這個自有屬性,並且不能通過 aa.c 來修改 aa.__proto__.c 即:

aa.c = 'ss' 是不能改變 aa.__proto__.c 的值

 

__________________________________________________________

所以,清楚了  __proto__ 是一個對象引用,並且瞭解了它的特殊作用 js 的原型鏈 面向對象 也就明白八成了吧~~!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章