1. 程式人生 > >JavaScript初學者必看“new”

JavaScript初學者必看“new”

譯者按: 本文簡單的介紹了new, 更多的是介紹原型(prototype),值得一讀。

為了保證可讀性,本文采用意譯而非直譯。

JavaScript初學者必看“new”

當你使用new的時候,會:

  1. 建立一個新的空物件;
  2. this繫結到該物件;
  3. 新增一個名為__proto__的新屬性,並且指向建構函式的原型(prototype);
  4. 返回該this物件。

如果你沒有特別理解,那麼我們接下來用例子來詳細解釋。首先定義一個建構函式Student,該函式接收兩個引數name

age

function Student(name, age){
  this.name = name;
  this.age = age;
}

現在我們使用new來建立一個新的物件:

var first = new Student('John', 26);

到底發生了什麼呢?

  1. 一個新的物件建立,我們叫它obj
  2. this繫結到obj,任何對this的引用就是對obj的引用;
  3. __proto__屬性被新增到obj物件。obj.__proto__會指向Student.prototype
  4. obj物件被賦值給first變數。

我們可以通過列印測試:

console.log(first.name);
// John

console.log(first.age);
// 26

接下來深入看看__proto__是怎麼回事。

原型(Prototype)

每一個JavaScript物件都有一個原型。所有的物件都從它的原型中繼承物件和屬性。

開啟瀏覽器開發者控制面板(Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J),輸入之前定義的Student函式:

function Student(name, age) {
  this.name = name;
  this.age = age;
}

為了證實每一個物件都有原型,輸入:

Student.prototype;
// Object {...}

你會看到返回了一個物件。現在我們來嘗試定義一個新的物件:

var second = new Student('Jeff', 50);

根據之前的解釋,second指向的物件會有一個__proto__屬性,並且應該指向父親的prototype,我們來測試一下:

second.__proto__ === Student.prototype
// true

Student.prototype.constructor會指向Student的建構函式,我們打印出來看看:

Student.prototype.constructor;
//  function Student(name, age) {
//    this.name = name;
//    this.age = age;
//  }

好像事情越來越複雜了,我們用圖來形象描述一下:JavaScript初學者必看“new”

Student的建構函式有一個叫.prototype的屬性,該屬性又有一個.constructor的屬性反過來指向Student構造。它們構成了一個環。當我們使用new去建立一個新的物件,每一個物件都有.__proto__屬性反過來指向Student.prototype

這個設計對於繼承來說很重要。因為原型物件被所有由該建構函式建立的物件共享。當我們新增函式和屬性到原型物件中,其它所有的物件都可以使用。

在本文我們只建立了兩個Student物件,如果我們建立20,000個,那麼將屬性和函式放到prototype而不是每一個物件將會節省非常很多的儲存和計算資源。

我們來看一個例子:

Student.prototype.sayInfo = function(){
  console.log(this.name + ' is ' + this.age + ' years old');
}

我們為Student的原型添加了一個新的函式sayInfo -- 所以使用Student建立的學生物件都可以訪問該函式。

second.sayInfo();
// Jeff is 50 years old

建立一個新的學生物件,再次測試:

var third = new Student('Tracy', 15);
// 如果我們現在列印third, 雖然只會看到年齡和名字這兩個屬性,
// 仍然可以訪問sayInfo函式。
third;
// Student {name: "Tracy", age: 15}
third.sayInfo();
// Tracy is 15 years old

在JavaScript中,首先檢視當前物件是否擁有該屬性;如果沒有,看原型中是否有該屬性。這個規則會一直持續,直到成功找到該屬性或則到最頂層全域性物件也沒找到而返回失敗。

繼承讓你平時不需要去定義toString()函式而可以直接使用。因為toString()這個函式內建在Object的原型上。每一個我們建立的物件最終都指向Object.prototype,所以可以呼叫toString()。當然, 我們也可以重寫這個函式:

var name = {
  toString: function(){
    console.log('Not a good idea');
  }
};
name.toString();
// Not a good idea

建立的name物件首先檢視是否擁有toString,如果有就不會去原型中查詢。

總結

也許這些概念對你來說有點多,但是當你理解了,使用原型可以讓你寫出更加高效的程式碼。

關於Fundebug

Fundebug專注於JavaScript、微信小程式、微信小遊戲、支付寶小程式、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了7億+錯誤事件,得到了Google、360、金山軟體、百姓網等眾多知名使用者的認可。歡迎免費試用!

JavaScript初學者必看“new”

版權宣告

轉載時請註明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/05/25/javascript-new-for-beginner/