沒有對象?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須要什麼。

  1. 建立一個函數,可返回一個新的對象
  2. 須要訪問到Student組織函數里的屬性
  3. 須要訪問到Student.prototype中的屬性和要領

詳細步驟剖析

一、參數通報

若要完成上面代碼的雷同效果,起首明白須要一個“類”的參數,以及別的參數(如name)。
js 的函數參數異常天真,形參數目可不肯定(運用...args),也可不給出。函數中有一個 與生俱來的arguments對象,具有length屬性,但不是數組,所以不可運用數組要領。

arguments 簡樸剖析

下述代碼中的輸出語句效果即為所傳實參的鳩合:

{ ‘0’: [Function: Student], ‘1’: ‘小明’, ‘2’: 18 }

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

二、要領完成

1.獲得 Student 類的組織函數

由前面 arguments 簡樸剖析可知,arguments中的第一個參數即為Student的組織函數。上面說到,arguments 並不是數組,那我們怎樣獲得第一項呢?

兩種要領:[].shift.call(arguments)Array.from(arguments)

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

2.建立一個新的對象

建立一個新的對象異常簡樸,以下:

const obj = new Object();

3.設置新對象的 __proto__ 屬性

__proto__是對象的私有屬性,指向組織該對象的組織函數的原型。所以此步須將新的對象的此屬性指向 Constructor的原型。

obj.__proto__ = Constructor.prototype;

4.獲得組織函數上的 this 屬性

若要實例化一個“類”,則必需挪用其組織函數,在實行組織函數時,其 this的值是動態的變化的,即為當前挪用該函數的對象。

但是這裡有個題目,若此時直接挪用組織函數並傳值

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等要領的一些運用。收成頗豐。

    原文作者:chord
    原文地址: https://segmentfault.com/a/1190000015271766
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞