【相關推薦:】
什麼是new
呢?
new
運運算元建立一個使用者定義的物件型別的範例或具有建構函式的內建物件型別之一。
光看定義還是有幾分晦澀,直接看一個具體的例子,來了解一下JavaScript
中的new
實現的功能。
// 現實中瘦不了,但網路中一定要保持苗條 function Thin_User(name, age) { this.name = name; this.age = age; } Thin_User.prototype.eatToMuch = function () { // 白日做夢吧,留下肥胖的淚水 console.log('i eat so much, but i\'m very thin!!!'); } Thin_User.prototype.isThin = true; const xiaobao = new Thin_User('zcxiaobao', 18); console.log(xiaobao.name); // zcxiaobao console.log(xiaobao.age); // 18 console.log(xiaobao.isThin); // true // i eat so much, but i'm very thin!!! xiaobao.eatToMuch();
通過上面這個例子,我們可以發現xiaobao
可以:
Thin_User
中屬性Thin_User.prototype
中屬性描述得更直白一點,new
做了這些事:
__proto__->Thin_User.prototype
this
指向新物件由於new
是關鍵字,我們無法像模擬陣列高階方法一樣覆蓋,因此我們寫一個函數createObject
,來模擬new
的效果。使用具體如下:
function Thin_User(name, age) {} const u1 = new Thin_user(...) const u2 = createObject(Thin_User, ...a\)
根據上面分析,createObject
編寫的大致步驟為:
obj
obj.__proto__->constructor.prototype
(但JavaScript不推薦直接修改__proto__屬性,提供了setPrototypeOf方法來專門修改原型)constructor.call/apply(obj, ...)
,將屬性新增到obj
上obj
__proto__和prototype
,可以看JavaScript之徹底理解原型與原型鏈call/apply
,可以看JavaScript之手撕call、apply
學習完這些,我們就可以編寫第一版程式碼:
function createObject(Con) { // 建立新物件obj // var obj = {};也可以 var obj = Object.create(null); // 將obj.__proto__ -> 建構函式原型 // (不推薦)obj.__proto__ = Con.prototype Object.setPrototypeOf(obj, Con.prototype); // 執行建構函式 Con.apply(obj, [].slice.call(arguments, 1)); // 返回新物件 return obj;}
眾所周知,函數是有返回值的,那建構函式如果有返回值,最終執行new
後返回的結果是怎樣的那?
假設建構函式返回值為一個基本型別,我們來看一下最後的返回結果:
function Thin_User(name, age) { this.name = name; this.age = age; return 'i will keep thin forever'; } Thin_User.prototype.eatToMuch = function () { console.log('i eat so much, but i\'m very thin!!!'); } Thin_User.prototype.isThin = true; const xiaobao = new Thin_User('zcxiaobao', 18); console.log(xiaobao.name); // zcxiaobao console.log(xiaobao.age); // 18 console.log(xiaobao.isThin); // true // i eat so much, but i'm very thin!!! xiaobao.eatToMuch();
最後的返回結果好像受到任何干擾,難道建構函式不會對返回值進行處理嗎?
不急,我們來接著測試一下返回值為物件的情況。
function Thin_User(name, age) { this.name = name; this.age = age; return { name: name, age: age * 10, fat: true } } Thin_User.prototype.eatToMuch = function () { // 白日做夢吧,留下肥胖的淚水 console.log('i eat so much, but i\'m very thin!!!'); } Thin_User.prototype.isThin = true; const xiaobao = new Thin_User('zcxiaobao', 18); // Error: xiaobao.eatToMuch is not a function xiaobao.eatToMuch();
當我執行eatToMuch
時,控制檯直接報錯,沒有當前函數,於是我列印了xiaobao
物件:
發現xiaobao
物件的age
發生了改變,而且增加了fat
屬性,正好與建構函式的返回值一樣。
看完這兩個例子,基本可以理清建構函式有返回值的情況:當建構函式返回值為物件時,直接返回這個物件。
function createObject(Con) { // 建立新物件obj // var obj = {};也可以 var obj = Object.create(null); // 將obj.__proto__ -> 建構函式原型 // (不推薦)obj.__proto__ = Con.prototype Object.setPrototypeOf(obj, Con.prototype); // 執行建構函式,並接受建構函式返回值 const ret = Con.apply(obj, [].slice.call(arguments, 1)); // 若建構函式返回值為物件,直接返回該物件 // 否則返回obj return typeof(ret) === 'object' ? ret: obj;}
【相關推薦:】
以上就是JavaScript把new給拿捏住了的詳細內容,更多請關注TW511.COM其它相關文章!