new操作符具體干了什么?


一、是什么

JavaScript中,new操作符用於創建一個給定構造函數的實例對象

例子

 1 function Person(name, age){
 2     this.name = name;
 3     this.age = age;
 4 }
 5 Person.prototype.sayName = function () {
 6     console.log(this.name)
 7 }
 8 const person1 = new Person('Tom', 20)
 9 console.log(person1)  // Person {name: "Tom", age: 20}
10 t.sayName() // 'Tom'

從上面可以看到:

  • new 通過構造函數 Person 創建出來的實例可以訪問到構造函數中的屬性
  • new 通過構造函數 Person 創建出來的實例可以訪問到構造函數原型鏈中的屬性(即實例與構造函數通過原型鏈連接了起來)

現在在構建函數中顯式加上返回值,並且這個返回值是一個原始類型

1 function Test(name) {
2   this.name = name
3   return 1
4 }
5 const t = new Test('xxx')
6 console.log(t.name) // 'xxx'

可以發現,構造函數中返回一個原始值,然而這個返回值並沒有作用

下面在構造函數中返回一個對象

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'

從上面可以發現,構造函數如果返回值為一個對象,那么這個返回值會被正常使用

二、流程

從上面介紹中,我們可以看到new關鍵字主要做了以下的工作:

  • 創建一個新的對象obj

  • 將對象與構建函數通過原型鏈連接起來

  • 將構建函數中的this綁定到新建的對象obj

  • 根據構建函數返回類型作判斷,如果是原始值則被忽略,如果是返回對象,需要正常處理

舉個例子:

1 function Person(name, age){
2     this.name = name;
3     this.age = age;
4 }
5 const person1 = new Person('Tom', 20)
6 console.log(person1)  // Person {name: "Tom", age: 20}
7 t.sayName() // 'Tom'

流程圖如下:

 

 

 

三、手寫new操作符

現在我們已經清楚地掌握了new的執行過程

那么我們就動手來實現一下new

 1 function mynew(Func, ...args) {
 2     // 1.創建一個新對象
 3     const obj = {}
 4     // 2.新對象原型指向構造函數原型對象
 5     obj.__proto__ = Func.prototype
 6     // 3.將構建函數的this指向新對象
 7     let result = Func.apply(obj, args)
 8     // 4.根據返回值判斷
 9     return result instanceof Object ? result : obj
10 }

測試一下

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

可以發現,代碼雖然很短,但是能夠模擬實現new


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM