new 運算符創建一個用戶定義的對象類型的實例或具有構造函數的內置對象的實例。
例1
function Person(name, age) {
this.name = name;
this.age = age;
}
var child = new Person('sam', 18);
new Person() 過程種發生了什麼:
(1)創建了一個新對象
(2)這個新對象 的__proto__指向了Person的原型對象。
不懂請看:深入JavaScript 從原型到原型鏈
(3)將構造函數的作用域賦給新對象(this就指向了這個新對象)
模擬實現new第一版:
var obj = {};
obj.__proto__ = Person.prototype;
Person.apply(obj, ['sam', 18]);
我們再將其封裝到函數裏:型如objectFactory(構造函數, 構造函數的形參)
function objectFactory() {
var obj = {};
var cons = [].shift.call(arguments);//把arguments[0]抽出來
obj.__proto__ = cons.prototype;
cons.apply(obj, arguments);
return obj;
}
//test
var child = objectFactory(Person, 'sam2', 118);
console.log(child2);
輸出:Person {name: “sam2”, age: 118}
例2
function Person1(name) {
this.name = name;
// 沒有返回值
}
function Person2(name) {
this.name = name;
return name;
// 返回非對象
}
function Person3(name) {
this.name = name;
return { a: 1 };
// 返回對象
}
function Person4(name) {
this.name = name;
return null;
// 返回null
}
var p1 = new Person1("aa");
var p2 = new Person2("bb");
var p3 = new Person3("cc");
var p4 = new Person4("dd");
console.log(p1); // Person1 {name: "aa"}
console.log(p2); // Person2 {name: "bb"}
console.log(p3); // {a: 1}
console.log(p4); // Person4 {name: "dd"}
通過上面我們發現:當使用 new 來創建對象時,如果函數沒有返回值 或 返回值是非對象,那麼返回的就是構造函數實例後的對象;如果函數return對象,那麼返回這個對象。
null不是對象。
期望此處引用一個對象,但又不知道引用什麼,這時用null,表空缺.
思路:
① 既然要判斷構造函數的返回值類型,很明顯從cons.apply(obj, arguments)入手,改爲 var result = cons.apply(obj, arguments);
② 先不考慮null的情況,把最後一句改爲return typeof result === ‘object’ ? result : obj;
③再考慮null的情況,加一層判斷,改爲return typeof result === ‘object’ ? result || obj : obj;
模擬實現new第二版:
function objectFactory() {
var obj = {};
var cons = [].shift.call(arguments);//把arguments[0]抽出來
obj.__proto__ = cons.prototype;
var result = cons.apply(obj, arguments);
return typeof result === 'object' ? result || obj : obj;
}