1、建立對象
1.構造函數
var Vehicle = function () {
this.price = 1000;
};數組
var v = new Vehicle();
v.price // 1000app
new命令自己就能夠執行構造函數,因此後面的構造函數能夠帶括號,也能夠不帶括號。下面兩行代碼是等價的,可是爲了表示這裏是函數調用,推薦使用括號。函數
// 推薦的寫法
var v = new Vehicle();
// 不推薦的寫法
var v = new Vehiclethis
一個很天然的問題是,若是忘了使用new命令,直接調用構造函數會發生什麼事?prototype
這種狀況下,構造函數就變成了普通函數,並不會生成實例對象。並且因爲後面會說到的緣由,this這時表明全局對象,將形成一些意想不到的結果。對象
var Vehicle = function (){
this.price = 1000;
};繼承
var v = Vehicle();
v // undefined
price // 1000
上面代碼中,調用Vehicle構造函數時,忘了加上new命令。結果,變量v變成了undefined,而price屬性變成了全局變量。所以,應該很是當心,避免不使用new命令、直接調用構造函數ip
爲了保證構造函數必須與new命令一塊兒使用,一個解決辦法是,構造函數內部使用嚴格模式,即第一行加上use strict。這樣的話,一旦忘了使用new命令,直接調用構造函數就會報錯。字符串
function Fubar(foo, bar){
'use strict';
this._foo = foo;
this._bar = bar;
}get
Fubar()
// TypeError: Cannot set property '_f
上面代碼的Fubar爲構造函數,use strict命令保證了該函數在嚴格模式下運行。因爲嚴格模式中,函數內部的this不能指向全局對象,默認等於undefined,致使不加new調用會報錯(JavaScript 不容許對undefined添加屬性)。
2.object.create()
2、new 命令的原理
使用new命令時,它後面的函數依次執行下面的步驟。
建立一個空對象,做爲將要返回的對象實例。
將這個空對象的原型,指向構造函數的prototype屬性。
將這個空對象賦值給函數內部的this關鍵字。
開始執行構造函數內部的代碼。
也就是說,構造函數內部,this指的是一個新生成的空對象,全部針對this的操做,都會發生在這個空對象上。構造函數之因此叫「構造函數」,就是說這個函數的目的,就是操做一個空對象(即this對象),將其「構造」爲須要的樣子
3、構造函數裏return(new老是返回一個對象)
若是構造函數內部有return語句,並且return後面跟着一個對象,new命令會返回return語句指定的對象;不然,就會無論return語句,返回this對象。
var Vehicle = function () {
this.price = 1000;
return 1000;
};
(new Vehicle()) === 1000
// false
上面代碼中,構造函數Vehicle的return語句返回一個數值。這時,new命令就會忽略這個return語句,返回「構造」後的this對象。
可是,若是return語句返回的是一個跟this無關的新對象,new命令會返回這個新對象,而不是this對象。這一點須要特別引發注意。
var Vehicle = function (){
this.price = 1000;
return { price: 2000 };
};
上面代碼中,構造函數Vehicle的return語句,返回的是一個新對象。new命令會返回這個對象,而不是this對象
(new Vehicle()).price
// 2000
4、函數的new
另外一方面,若是對普通函數(內部沒有this關鍵字的函數)使用new命令,則會返回一個空對象。
function getMessage() {
return 'this is a message';
}
var msg = new getMessage();
msg // {}
typeof msg // "object"
上面代碼中,getMessage是一個普通函數,返回一個字符串。對它使用new命令,會獲得一個空對象。這是由於new命令老是返回一個對象,要麼是實例對象,要麼是return語句指定的對象。本例中,return語句返回的是字符串,因此new命令就忽略了該語句。
5、new命令簡化的內部流程
function _new(/ 構造函數 / constructor, / 構造函數參數 / params) {
// 將 arguments 對象轉爲數組
var args = [].slice.call(arguments);
// 取出構造函數
var constructor = args.shift();
// 建立一個空對象,繼承構造函數的 prototype 屬性
var context = Object.create(constructor.prototype);
// 執行構造函數
var result = constructor.apply(context, args);
// 若是返回結果是對象,就直接返回,不然返回 context 對象
return (typeof result === 'object' && result != null) ? result : context;
}
// 實例var actor = _new(Person, '張三', 28);