首先先來段我們熟悉的代碼
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.say = function(){
console.log('i can speak');
}
let girl = new Person('weboof', 18);
console.log(girl.name);
console.log(girl.age);
girl.say();
這是我們經(jīng)??吹讲⑶页S玫拇a,由此可以看出通過new創(chuàng)建出來的實例有以下幾個特征:
- new通過構(gòu)造函數(shù)Person創(chuàng)造出來的實例可以訪問構(gòu)造函數(shù)中定義的屬性和方法。
- new通過構(gòu)造函數(shù)Person創(chuàng)造出來的實例可以訪問構(gòu)造函數(shù)原型上的屬性和方法。
接下來,按照以上總結(jié)內(nèi)容,我們試著自己實現(xiàn)以下new操作符。首先我們需要了解以下幾個問題點:
- 如何讓實例和構(gòu)造函數(shù)產(chǎn)生關(guān)系,如何實現(xiàn)屬性和方法的繼承?
- 如何讓實例和構(gòu)造函數(shù)的原型產(chǎn)生關(guān)聯(lián)?
簡易版
function creat(Construction, ...args){
let obj = {};
Construction.call(obj, ...args); //繼承構(gòu)造函數(shù)內(nèi)部屬性和方法
//Construction.apply(obj, args); //繼承構(gòu)造函數(shù)內(nèi)部屬性和方法
Object.setPrototypeOf(obj, Construction.prototype); //連接原型
return obj;
}
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.say = function(){
console.log('i can speak');
}
let girl = creat(Person, 'weboof', 18);
console.log(girl.name); //weboof
console.log(girl.age); //18
girl.say(); // i can speak
我們看到以上方法已經(jīng)可以實現(xiàn)一個簡易的new操作符了。接下來我們還需要討論一下,當(dāng)構(gòu)造函數(shù)有返回值時, 會出現(xiàn)什么情況?
構(gòu)造函數(shù)返回原始類型
function Person(name, age) {
this.name = name;
this.age = age;
return 1
}
Person.prototype.say = function(){
console.log('i can speak');
}
let girl = new Person('weboof', 18);
console.log(girl.name); //weboof
console.log(girl.age); //18
girl.say(); //i can speak
由此,我們可以看出,如果構(gòu)造函數(shù)返回值為原始類型時,對于創(chuàng)建出來的實例不會有任何影響。
構(gòu)造函數(shù)返回對象類型
function Person(name, age) {
this.name = name;
this.age = age;
return {
name: 'hanhh'
}
}
Person.prototype.say = function(){
console.log('i can speak');
}
let girl = new Person('weboof', 18);
console.log(girl.name); //hanhh
console.log(girl.age); //undefined
girl.say(); //VM267:17 Uncaught TypeError: girl.say is not a function
由此可以看出,如果構(gòu)造函數(shù)返回的值為對象類型,通過構(gòu)造函數(shù)創(chuàng)建出的實例是會受到返回值的影響,并且不會繼承構(gòu)造函數(shù)原型鏈上的屬性和方法。
完整代碼如下
function creat(con, ...args) {
//con為傳進來的構(gòu)造函數(shù)
let obj = {};
//obj可以訪問構(gòu)造函數(shù)上面的屬性和方法
// let result = con.call(obj, ...args);
let result = con.apply(obj, args);
if(result instanceof Object) {
return result;
}else {
Object.setPrototypeOf(obj, con.prototype); //obj可以訪問構(gòu)造函數(shù)原型鏈上的屬性
return obj;
}
}
以上就是對new操作符的詳細解釋,希望對你有幫助~