new原理及模擬實現

簡介new

new 運算符是建立一個用戶定義的對象類型的實例或具備構造函數的內置對象的實例,其建立過程以下:javascript

  • 建立一個空的簡單JavaScript對象(即{})
  • 連接該對象(即設置該對象的構造函數)到另外一個對象
  • 將第一步新建立的對象做爲this的上下文
  • 若是該函數沒有返回對象,則返回this

舉個栗子:java

function Person(name,age){
    this.name = name;
    this.age = age;
    this.habit = "swim";
}

Person.prototype.sex = 'female';

Person.prototype.sayHello = function(){
    console.log('Hello!My name is ' + this.name);
}

var person = new Person('Youxuan','20');

console.log(person.name);   //Youxuan
console.log(person.habit);  //swim
console.log(person.sex);    //female
person.sayHello();  //Hello!My name is Youxuan

從上述內容中,能夠看出實例訪問到Person構造函數裏的屬性,
也能夠訪問到Person.prototype裏的屬性;
所以,咱們能夠嘗試模擬一下new的實現方法,先來回顧一下new是如何使用的數組

function Person(){
    ...
}
var person = new Person(...);
var person = newObject(...);

初步模擬

由於new的結果是一個對象,因此在實現new的過程當中,也要生成一個新的對象。咱們先將這個對象命名爲obj,由於obj也具備Person構造函數的屬性,全部要經過調用父類,繼承父類實例的方式,來給obj添加新屬性。微信

回顧上一篇文章,咱們講解了原型和原型鏈,把obj的proto指向構造函數Person的原型對象prototype,此時便創建了obj對象的原型鏈:app

obj->Person.prototype->Object.prototype->null,實例以此關係來訪問原型上的屬性函數

function newObject(){
    var obj = new Object();
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    Constructor.apply(obj,arguments);
    return obj;
}

在以上內容中,經過new Object()建立了一個對象obj。this

取出第一個參數,就是咱們要傳入的構造函數。由於shift會修改原數組,因此arguments會被去除第一個參數。spa

將obj的原型指向構造函數,這樣obj就能夠訪問到構造函數原型中的屬性。prototype

利用apply,改變構造函數this指向到新建對象,這樣obj就能訪問到構造函數中的屬性,而後返回obj。code

如今,咱們寫一段代碼來驗證一下效果:

function Person(name,age){
    this.sex = 'female';
    this.age = age;
    return {
        name: name,
        habit: 'swim'
    }
}
var person = new Person('Youxuan','20');
console.log(person.name);   //Youxuan
console.log(person.habit);  //swim
console.log(person.sex);    //undefined
console.log(person.age);    //undefined

以上代碼中,構造函數返回了一個對象,在實例person中只能訪問返回的對象中的屬性。

並且另需注意,這裏返回的是一個對象,倘若須要返回一個基本類型的數據時該怎麼辦呢?

function Person(name,age){
    this.sex = 'female';
    this.age = age;
    return 'Beauty on my face'
}
var person = new Person('Youxuan','20');
console.log(person.name);       //undefined
console.log(person.habit);      //undefined
console.log(person.sex);        //female
console.log(person.age);        //20

這時結果跟上次徹底相反,儘管此次有返回值,可是至關於沒有對返回值進行處理。

效果實現

因此仍需判斷返回值是否是一個對象,若是是一個對象,就返回這個對象;若是不是一個對象,那就將它直接返回:

function newObject(){
    var obj = new Object();
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    var demo = Constructor.apply(obj,arguments);
    return typeof demo === 'object' ? demo : obj;
}

至此就模擬實現了new操做符的效果,主要原理就是原型鏈apply繼承。

對此你有什麼感覺呢,歡迎添加微信進行交流。


圖片描述

相關文章
相關標籤/搜索