模擬new實例化對象。


使用new和字面量的的方法是兩種主流創建對象的方法,兩種最終都能達到同樣的實例化的對象,本章主要圍繞new關鍵字來實例化一個對象並且講一個不使用new但是完全與new實例化對象相同的例子。

在使用new后面跟一個構造函數的時候,將會返回一個新對象,

這個對象中的屬性便就是new后面跟的構造函數中的this的屬性

這個對象的__proto__屬性指向就是new后面的構造函數的prototype屬性。

prototype屬性的值是一個對象,是Javascript為每一個函數內置的一個屬性,也就是說,所有的函數都能成為構造函數,所以不到萬不得已不要覆蓋原來的值,更加不要使用基本類型覆蓋prototype屬性。

new可以總結為下面幾個步驟:

  1. 創建一個新對象
  2. 把這個新對象的__proto__指向構造函數的prototype屬性
  3. 把構造函數中的this上的屬性全部添加到新對象
  4. 返回這個新對象

通過這四個步驟,返回了一個新實例化對象,牢記這四個步驟,就能輕松的模擬出new的效果,或者通過new模擬字面量的表示法。

假設現在有一個構造函數

//構造函數首字母大寫並不是強烈要求,只是一種書寫的規范
function Fun(){
    this.a = 1;
    this.b = "字符串";
    this.arr = [1,2]
}
//每個函數中都內置了一個prototype屬性
//可以通過console.log(Fun.prototype)打印出來看看
Fun.prototype.c = "prototype"
//不要直接覆蓋prototype,就像下面這個例子 // Fun.prototype = "obj" //但是如果非要覆蓋的話,你可以這樣做 // Fun.prototype = { // constructor:Fun // 把constructor屬性指回構造函數 // 可以達到一樣的效果 // }

執行上面的代碼,接下來只需要 new Fun() 就可以返回一個新對象,並且這個對象里面擁有a,b,arr的屬性,原型鏈__proto__上擁有c這個屬性,它的結構是這樣的

 1 //一些只是表示結構。不能執行
 2 Fun {
 3 
 4     a:1,
 5     b:"字符串",
 6     arr:[1,2]
 7     __proto__:{
 8         c : "prototype",
 9         constructor:function Fun()
10         __proto__: ......
11     }
12 }

但是,這並不是目的,目的是希望不通過new來得到一個新對象並且跟new出來一樣的結果。

首先執行第一步(返回一個新對象):

1 //通過字面量創建一個新對象 
2  var obj = {} 

得到這個對象之后把這個對象的__proto__指向prototype

//這里__proto__與prototype的值都是對象
//最終對象的原型鏈都將指向一個帶get,set方法的超級對象
//__proto__是對象的原型鏈屬性
//prototype是構造函數的一個屬性
obj.__proto__ = Fun.prototype

然后需要把構造函數中this的屬性全部拷貝到對象的中,這時可以使用call或在apply方法。

1 //把obj作為第一個參數傳入到call中
2 //這是Fun中的this就變成了obj
3 //Fun通過call執行之后,this中的屬性就被拷貝到了obj中
4 Fun.call(obj)
5 //或在Fun.apply(obj)
6 //兩個方法僅有的區別就是所傳的參數不同。

最后打印一下obj,發現它與new出來的對象幾乎沒有差異

 

以下是完整代碼

function Fun(){
     this.a = 1;
     this.b = "字符串";
     this.arr = [1,2]
 }
Fun.prototype.c = "prototype";
var obj = {};
obj.__proto__ = Fun.prototype;
Fun.call(obj)
var newObj = new Fun();
console.log(obj);
console.log(newObj);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM