1. 不使用new,函數正常執行,如有`return`語句,`return`的值做爲返回值,若沒有,在函數體執行完畢後返回`undefined`。 ``` function Foo(){} //建立一個函數 var b = Foo(x, y, z); //執行這個函數而且把值賦值給b ``` 2. 使用new - 建立一個空對象,而且把this指向該對象 - 把這個對象的原型(`__proto__`)賦值爲函數的【`prototype`】屬性(`Foo.prototype`) - 若是函數執行了`return`語句且返回值的類型是對象,則以該對象做爲`new`調用的結果。反之,將`this`做爲結果並返回。 ``` var c = new Foo(x, y, z); //下面是執行情況 function Foo(){ Foo.prototype.constructor : Foo;//隱式建立一個constructor屬性,指向它構造函數。 //這裏的this是不存在的,屬於內部機制,咱們這裏用雙方括號框起來只是爲了方便理解。 [[this]] = {}; [[this]].__proto__ = Foo.prototype; do something; return result; //在執行上面一句代碼時會進行如下的判斷。 if(result is Object){ return result }else{ return [[this]]; } } ``` 順便說一點關於`constructor`: 衆所周知,經過`constructor`來判斷一個對象它的構造函數,實際上這個`constructor`並非當前對象的屬性,這個值來自於這個對象的原型 ``` var d = new Foo; d.constructor //Foo d.constructor === Foo; //true //d自己並無construtor屬性,它會向上查找它的原型鏈 d.hasOwnProperty("constructor");//false d.__proto__.hasOwnProperty("constructor");//true d.prototype.constructor //Foo ``` ### 備註: 1. `__proto__` : 原型,這個屬於javascript引擎內部實現的,可是爲了方便調試,v8引擎把它暴露的出來,如今瀏覽器大多數都實現了這個。 2. `prototype` : 每個函數默認都會有一個`prototype`屬性,該屬性是一個對象,只有一個key:`constructor`,指向構造函數自己。 - 這一段比較繞,有毅力的同窗能夠看完: - `prototype`屬性,將做爲使用`Foo`做爲構造函數,`new`出來的對象的【原型】。 - 而`Foo`自己的原型是(`Function.prototype`), - `Foo`的原型:`Foo.__proto__`,`Foo`的`prototype`屬性:`Foo.prototype。` 3. `constructor` : 構造函數,能夠理解成,當前對象是由哪一個函數構造的,構造出來的對象並無這個屬性,這個屬性在構造函數的自己,而且指向它本身,構造出來的函數是經過原型鏈(`__proto__`)來訪問到它的。 4. `hasOwnProperty` :檢測屬性,這個是屬於js內置的對象方法,用來檢測給定的名字是不是對象的自有屬性。 5. 函數的【原型】是:`Foo.__proto` 它等價於`Function.prototype` 6. 羣友 王重陽:記住`function`對象才同時擁有`__proto__`和`prototype`屬性,而這兩個是不一樣的東西。而用`function`構造函數`new`的對象只有`__proto__`而且等於其構造函數的`prototype`。
感謝ECMAScript羣熱心網友提出的問題和修改意見。特別感謝@先知javascript