一、是什么
在JavaScript
中,new
操作符用于創(chuàng)建一個(gè)給定構(gòu)造函數(shù)的實(shí)例對象
例子
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name)
}
const person1 = new Person('Tom', 20)
console.log(person1) // Person {name: "Tom", age: 20}
t.sayName() // 'Tom'
從上面可以看到:
-
new
通過構(gòu)造函數(shù)Person
創(chuàng)建出來的實(shí)例可以訪問到構(gòu)造函數(shù)中的屬性 -
new
通過構(gòu)造函數(shù)Person
創(chuàng)建出來的實(shí)例可以訪問到構(gòu)造函數(shù)原型鏈中的屬性(即實(shí)例與構(gòu)造函數(shù)通過原型鏈連接了起來)
現(xiàn)在在構(gòu)建函數(shù)中顯式加上返回值竟闪,并且這個(gè)返回值是一個(gè)原始類型
function Test(name) {
this.name = name
return 1
}
const t = new Test('xxx')
console.log(t.name) // 'xxx'
可以發(fā)現(xiàn),構(gòu)造函數(shù)中返回一個(gè)原始值杖狼,然而這個(gè)返回值并沒有作用
下面在構(gòu)造函數(shù)中返回一個(gè)對象
function Test(name) {
this.name = name
console.log(this) // Test { name: 'xxx' }
return { age: 26 }
}
const t = new Test('xxx')
console.log(t) // { age: 26 }
console.log(t.name) // 'undefined'
從上面可以發(fā)現(xiàn)炼蛤,構(gòu)造函數(shù)如果返回值為一個(gè)對象,那么這個(gè)返回值會被正常使用
二蝶涩、流程
從上面介紹中理朋,我們可以看到new
關(guān)鍵字主要做了以下的工作:
創(chuàng)建一個(gè)新的對象
obj
將對象與構(gòu)建函數(shù)通過原型鏈連接起來
將構(gòu)建函數(shù)中的
this
綁定到新建的對象obj
上根據(jù)構(gòu)建函數(shù)返回類型作判斷,如果是原始值則被忽略子寓,如果是返回對象暗挑,需要正常處理
舉個(gè)例子:
function Person(name, age){
this.name = name;
this.age = age;
}
const person1 = new Person('Tom', 20)
console.log(person1) // Person {name: "Tom", age: 20}
t.sayName() // 'Tom'
流程圖如下:
1.png
三、手寫new操作符
現(xiàn)在我們已經(jīng)清楚地掌握了new
的執(zhí)行過程
那么我們就動手來實(shí)現(xiàn)一下new
function mynew(Func, ...args) {
// 1.創(chuàng)建一個(gè)新對象
const obj = {}
// 2.新對象原型指向構(gòu)造函數(shù)原型對象
obj.__proto__ = Func.prototype
// 3.將構(gòu)建函數(shù)的this指向新對象
let result = Func.apply(obj, args)
// 4.根據(jù)返回值判斷
return result instanceof Object ? result : obj
}
測試一下
function mynew(func, ...args) {
const obj = {}
obj.__proto__ = func.prototype
let result = func.apply(obj, args)
return result instanceof Object ? result : obj
}
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.say = function () {
console.log(this.name)
}
let p = mynew(Person, "huihui", 123)
console.log(p) // Person {name: "huihui", age: 123}
p.say() // huihui
可以發(fā)現(xiàn)斜友,代碼雖然很短炸裆,但是能夠模擬實(shí)現(xiàn)new