JS中new到底發生了什么


outline

  1. prototype 與 __proto__
  2. function 與 object
  3. new 到底發生了什么

prototype 與 __proto__

首先說下在JS中比較容易讓人困惑的 prototype 和 __proto__ 
__proto__ 就是JavaScript中所謂的原型.

一個對象的 __proto__ 屬性和自己的內部屬性[[Prototype]]指向一個相同的值 (通常稱這個值為原型),原型的值可以是一個對象值也可以是null(比如說Object.prototype.__proto__ 的值就是null).該屬性可能會引發一些錯誤,因為用戶可能會不知道該屬性的特殊性,而給它賦值,從而改變了這個對象的原型. 如果需要訪問一個對象的原型,應該使用方法Object.getPrototypeOf.

firefox、chrome等瀏覽器把對象內部屬性[[Prototype]]用 __proto__ 的形式暴露了出來.(老版本的IE並不支持 __proto__ ,IE11中已經加上了 __proto__ 屬性)

prototype 是function中特有的.什么意思呢?舉個例子:

function A(name){  this.name = name; } console.dir(A); 

我們得到如下結果:

首先看A是一個函數,自然A的原型鏈就應該指向一個函數對象.

其次我們還看到當我們定義了function A的時候,A上會有一個 prototype 的屬性.這個屬性是我們定義function的時候就默認帶上的.A的 prototype 指向一個對象,這個對象的包含一個 constructor 屬性以及一個 __proto__ ( __proto__ 指向Object表示這是一個對象).默認的constructor屬性指向function A.

看起來有點混亂是不?這邊只要記住一點: __proto__ 是原型,prototype是函數默認的一個屬性,它指向一個對象,這個對象的constructor屬性指向函數本身.

function與object

首先看一個例子

function A(name){  this.name = name;  this.getName = function(){   console.log(this.name);  }  var b = 'test';  console.log(b); } var a = new A('testa'); A('TESTA'); 

當執行 var a = new A('testa'); 得到的a是這樣的:

而我們執行 A('TESTA'); 相當於:

//window.name = 'TESTA'(由於非strict模式下,this默認指向window) //window.getName = function(){console.log(this.name);} 

我們的函數A既可以直接執行,又可以new一下返回一個對象.function和object到底是什么關系,new的時候發生了什么?

new到底發生了什么

還是我們上面的問題,當我們執行 var a = new A('testa') 到底發生了什么.MDN上是這么說的

對於 var o = new Foo();

//JavaScript 實際上執行的是:
var o = new Object(); o.[[Prototype]] = Foo.prototype; Foo.call(o); 

這樣大概就明白了,當我們執行 new A('testa') 的時候

JS會這樣做

  1. var o = new Object();
  2. o. __proto__ = A.prototype;//這里還記得之那個function里面的默認的屬性么?
  3. A.call(o)//由於這里this是指向o,可以把什么this.name/getName綁定到o上.
  4. 把這個o返回給a;//完成var a = new A()的過程.

這里注意下,上面所謂的第4步其實是一個簡化的說法.真正的過程是在第3步之后,如果發現A返回是一個Object類型(非primitive類型,即非string,boolean,number,null,undefined類型就是Object類型),則直接返回A的返回值,否則把第1步new的Object返回出去.(默認情況下,JS中函數默認返回值是undefined)舉個例子

function A(name){  this.name = name;  this.getName = function(){   console.log(this.name);  }  var b = 'test';  console.log(b);  return {}; } var a = new A('testa');//{} 

這里我們把A函數的返回值設置為一個Object類型,則這個時候執行new A返回的就是A函數的返回值{}.如果我們把A的返回值設置為return [];那么我們在new A的時候也相應的得到一個空數組.

用 stackoverflow 上一個人的回答來總結下就是:

In JavaScript, most functions are both callable and instantiable: they have both a [[Call]] and [[Construct]] internal methods.

在JS中,絕大多數的函數都是既可以調用也可以實例化的.我們既可以直接執行函數得到函數的返回值.也可以通過new操作符得到一個對象.

原文地址:http://warjiang.github.io/devcat/2016/05/12/JS中new到底發生了什么/


免責聲明!

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



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