JavaScript把new給拿捏住了

本篇文章給大家帶來了關于javascript的相關知識,其中主要介紹了關于new的相關問題,new運算符創建一個用戶定義的對象類型的實例或具有構造函數的內置對象類型之一,希望對大家有幫助 。

JavaScript把new給拿捏住了

文章插圖

【相關推薦:javascript視頻教程】
前言什么是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); // zcxiaobaoconsole.log(xiaobao.age); // 18console.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); // zcxiaobaoconsole.log(xiaobao.age); // 18console.log(xiaobao.isThin); // true// i eat so much, but i'm very thin!!!xiaobao.eatToMuch();最后的返回結果好像受到任何干擾,難道構造函數不會對返回值進行處理嗎?
不急,我們來接著測試一下返回值為對象的情況 。
返回值為對象【JavaScript把new給拿捏住了】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 functionxiaobao.eatToMuch();當我執行eatToMuch時,控制臺直接報錯,沒有當前函數,于是我打印了xiaobao對象:
JavaScript把new給拿捏住了

文章插圖

發現xiaobao對象的age發生了改變,而且增加了fat屬性,正好與構造函數的返回值一樣 。
看完這兩個例子,基本可以理清構造函數有返回值的情況:當構造函數返回值為對象時,直接返回這個對象 。

推薦閱讀