沒有對象?new一個!

咱們都知道,使用new後可返回一個對象,一般用於實例化一個「類」。
用法:數組

function Student (name, age) {
    this.name = name;
    this.age = age;
}
Student.prototype.sayName = function() {
    console.log('I am '+ this.name);
}
const person =new Student('小明');
person.sayName();  // I am 小明

問題分析

首先咱們分析一下,手動實現new須要什麼。ruby

  1. 建立一個函數,可返回一個新的對象
  2. 須要訪問到Student構造函數裏的屬性
  3. 須要訪問到Student.prototype中的屬性和方法

具體步驟分析

1、參數傳遞

若要實現上面代碼的相同效果,首先明確須要一個「類」的參數,以及其它參數(如name)。
js 的函數參數很是靈活,形參數量可不肯定(使用...args),也可不給出。函數中有一個 與生俱來的arguments對象,具備length屬性,但不是數組,因此不可以使用數組方法。app

arguments 簡單分析

下述代碼中的輸出語句結果即爲所傳實參的集合:函數

{ '0': [Function: Student], '1': '小明', '2': 18 }學習

function objectFactory() {
    console.log(arguments);
}
const person = objectFactory(Student, '小明',18);

2、方法實現

1.獲得 Student 類的構造函數

由前面 arguments 簡單分析可知,arguments中的第一個參數即爲Student的構造函數。上面說到,arguments 並不是數組,那咱們如何獲得第一項呢?this

兩種方法:[].shift.call(arguments)Array.from(arguments)prototype

var Constructor = [].shift.call(arguments);

2.建立一個新的對象

建立一個新的對象很是簡單,以下:code

const obj = new Object();

3.設置新對象的 __proto__ 屬性

__proto__是對象的私有屬性,指向構造該對象的構造函數的原型。因此此步須將新的對象的此屬性指向 Constructor的原型。對象

obj.__proto__ = Constructor.prototype;

4.獲得構造函數上的 this 屬性

若要實例化一個「類」,則必須調用其構造函數,在執行構造函數時,其 this的值是動態的變化的,即爲當前調用該函數的對象。get

但是這裏有個問題,若此時直接調用構造函數並傳值

Constructor(arguments);

最終結果將爲undefined

這是爲何呢?

緣由是構造函數中的 this並無指向當前的新對象,此時apply()方法就可完美解決這個問題(call()方法也可),具體的apply()的使用及apply()call()的異同可參照大神文章

結果:

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

const person = objectFactory(Student, '小明', 18);
person.sayName();   // I am 小明

結束

對於手動實現new的學習,原型的概念更清晰了,在具體的實現過程當中也學習到了shiftcallapply等方法的一些使用。收穫頗豐。

相關文章
相關標籤/搜索