摘要:因?yàn)闃?gòu)造函數(shù)調(diào)用會將一個(gè)全新的對象作為變量的值,并隱式返回這個(gè)新對象作為調(diào)用的結(jié)果。一個(gè)開發(fā)者熟知的解決方案是,在調(diào)用函數(shù)前先判斷函數(shù)的接收者是否為當(dāng)前函數(shù)的實(shí)例。注意,上面二種解決方案都使用了操作符來判斷對象的實(shí)例。
在JavaScript中函數(shù)作為對象的屬性使用時(shí),我們稱其為方法調(diào)用;如果函數(shù)使用new操作符來調(diào)用時(shí),我們稱其為構(gòu)造函數(shù)。
在涉及到構(gòu)造函數(shù)時(shí),通常繞不開關(guān)于this的討論。因?yàn)闃?gòu)造函數(shù)調(diào)用會將一個(gè)全新的對象作為this變量的值,并隱式返回這個(gè)新對象作為調(diào)用的結(jié)果。
在使用構(gòu)造函數(shù)時(shí),如果調(diào)用者忘記使用new關(guān)健字,那么函數(shù)的接收者將是全局對象。
function Person(name, age) { this.name = name; this.age = age; } // 使用`new`調(diào)用 var jenemy = new Person("jenemy", 18); console.log(window.age); // undefined // 不使用 var jenemy = Person("jenemy", 18); console.log(window.age); // 18
不使用new調(diào)用構(gòu)造函數(shù)的結(jié)果是我們無意間創(chuàng)建了全局變量name和age,如果這些全局變量已經(jīng)存在則會被修改。
一個(gè)開發(fā)者熟知的解決方案是,在調(diào)用函數(shù)前先判斷函數(shù)的接收者是否為當(dāng)前函數(shù)的實(shí)例。
function Person(name, age) { if (!(this instanceof Person)) { return new Person(name, age); } this.name = name; this.age = age; }
這種模式的一個(gè)缺點(diǎn)是需要額外的函數(shù)調(diào)用,在性能上代價(jià)有點(diǎn)高。一種更為有效的方式是使用ES5的Object.create()函數(shù)。
function Person(name, age) { var self = this instanceof Person ? this : Object.create(Person.prototype); self.name = name; self.age = age; return self; }
注意,上面二種解決方案都使用了instance操作符來判斷對象的實(shí)例。如果看過我寫的《javascript判斷一個(gè)對象是否為數(shù)組》文章,會發(fā)現(xiàn)instanceof操作符并不可靠。上面的示例,稍作修改:
function Person(name, age) { this.name = name; this.age = age; } Object.defineProperty(Person, Symbol.hasInstance, { value(v) { return false; } }) var wu = new Person("jenemy", 18); console.log(wu instanceof Person); // false
如果沒有修改Person對象內(nèi)建的Symbol.hasInstance方法,上面的結(jié)果很顯然應(yīng)該在控制臺輸出true。為了解決函數(shù)調(diào)用這種模棱兩可的問題,ES6提供了元屬性new.target,當(dāng)調(diào)用函數(shù)的[[Construct]]方法時(shí),new.target被賦值為new操作的目標(biāo),通常為新創(chuàng)建對象的實(shí)例。
function Person(name, age) { if (!new.target) { throw "Peron must called with new"; } this.name = name; this.age = age; } var wu = Person("jenemy", 18); // Uncaught Peron must called with new
需要注意的是在函數(shù)外使用new.target會報(bào)語法錯(cuò)誤。同時(shí),它不受對象的Symbol.hasInstance方法被修改的影響。所以如果是在ES6環(huán)境,使用new.target是最可靠的解決方案。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/88521.html
摘要:注意基本變量類型不是對象類型,只有基本包裝類型才是對象類型。至于顯示的原型,在里用屬性表示,這個(gè)是原型繼承的基礎(chǔ)知識,在這里就不在敘述了。 前言 如果你要開發(fā)一個(gè)復(fù)雜的產(chǎn)品,那么肯定少不了使用面向?qū)ο髾C(jī)制,當(dāng)然也避不開 Javascript 里面的繼承,instanceof 運(yùn)算符是原生 Javascript 語言中用來判斷實(shí)例繼承的操作符。所以我們有必要深入理解該運(yùn)算符! inst...
摘要:三種使用構(gòu)造函數(shù)創(chuàng)建對象的方法和的作用都是在某個(gè)特殊對象的作用域中調(diào)用函數(shù)。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。叫法上把函數(shù)叫做構(gòu)造函數(shù),其他無區(qū)別適用情境可以在特殊的情況下用來為對象創(chuàng)建構(gòu)造函數(shù)。 一、工廠模式 工廠模式:使用字面量和object構(gòu)造函數(shù)會有很多重復(fù)代碼,在此基礎(chǔ)上改進(jìn)showImg(https://segmentfault.com/img/bVbmKxb?w=456&...
摘要:檢測函數(shù)從技術(shù)上講,中的函數(shù)是引用類型,同樣存在構(gòu)造函數(shù),每個(gè)函數(shù)都是其實(shí)例,比如不好的寫法然而,這個(gè)方法亦不能跨幀使用,因?yàn)槊總€(gè)幀都有各自的構(gòu)造函數(shù),好在運(yùn)算符也是可以用于函數(shù)的,返回。 上周寫過一篇讀書筆記《編寫可維護(hù)的JavaScript》之編程實(shí)踐,其中 第8章 避免『空比較』是博主在工作中遇坑較多的雷區(qū),所以特此把該章節(jié)重新整理分享,希望大家不再坑隊(duì)友(>﹏<)。 在 Jav...
摘要:這樣每個(gè)實(shí)例獨(dú)享自己的屬性,并和其他同類型的實(shí)例共享方法構(gòu)造函數(shù)原型以上這種方式定義的類型,可以通過來判斷一個(gè)實(shí)例是否是類型的實(shí)際上是通過實(shí)例的原型鏈來判斷一個(gè)對象是否某個(gè)類型的實(shí)例的,具體的細(xì)節(jié)后面會詳細(xì)介紹。 JavaScript面向?qū)ο缶幊? 如何定義自定義類型 首先需要明確,JavaScript并不是傳統(tǒng)意義上的OO語言,它并沒有class的概念, 而是包含了另一套異常強(qiáng)大的...
摘要:和的作用一樣,區(qū)別在于寫法語法對象對象作用判斷對象是否在對象的原型鏈上語法對象構(gòu)造函數(shù)作用判斷構(gòu)造函數(shù)的屬性是否在對象的原型鏈上,如果在,就返回屬性是否可枚舉用于檢查給定的屬性是否能夠使用語句。 ## javascript對象原型成員詳解 ## ECMAScript 中的對象就是一組數(shù)據(jù)和功能的集合,對象可以通過 new 操作符后跟要創(chuàng)建的對象名稱來...
閱讀 2486·2021-09-27 13:36
閱讀 2176·2019-08-29 18:47
閱讀 2143·2019-08-29 15:21
閱讀 1406·2019-08-29 11:14
閱讀 1991·2019-08-28 18:29
閱讀 1635·2019-08-28 18:04
閱讀 583·2019-08-26 13:58
閱讀 3222·2019-08-26 12:12