關於使用new和不使用new

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

相關文章
相關標籤/搜索