您好,登錄后才能下訂單哦!
參考文獻(xiàn)
JavaScript原型與繼承的秘密
__proto__
除null和undefined,JS中的所有數(shù)據(jù)類型都有這個(gè)屬性; 它表示當(dāng)我們?cè)L問一個(gè)對(duì)象的某個(gè)屬性時(shí),如果該對(duì)象自身不存在該屬性, 就從它的__proto__屬性上繼續(xù)查找,以此類推,直到找到,若找到最后還是沒有找到,則結(jié)果為undefined
我們把一個(gè)對(duì)象的__proto__屬性所指向的對(duì)象叫該對(duì)象的原型;我們可以修改一個(gè)對(duì)象的原型來(lái)讓這個(gè)對(duì)象擁有某種屬性或某個(gè)方法
// 修改一個(gè)Number類型的值的原型 const num = 1; num.__proto__.name = "My name is 1"; console.log(num.name); // My name is 1 // 修改一個(gè)對(duì)象的原型 const obj = {}; obj.__proto__.name = "dreamapple"; console.log(obj.name); // dreamapple
需注意的是,__proto__屬性雖多數(shù)瀏覽器支持,但其實(shí)它僅在ECMAScript 2015規(guī)范中才被準(zhǔn)確定義, 目的是為了給這個(gè)傳統(tǒng)的功能定制一個(gè)標(biāo)準(zhǔn),以確保瀏覽器間的兼容性。通過(guò)使用__proto__屬性來(lái)修改一個(gè)對(duì)象的原型非常慢且影響性能。 所以,若想獲取一個(gè)對(duì)象的原型,推薦用Object.getPrototypeOf 或Reflect.getPrototypeOf,設(shè)置一個(gè)對(duì)象的原型推薦用Object.setPrototypeOf或Reflect.setPrototypeOf
prototype
首先要記住的是,該屬性一般只存在于函數(shù)對(duì)象上; 只要是能作為構(gòu)造器的函數(shù),都包含這個(gè)屬性。即只要這個(gè)函數(shù)能通過(guò)new生成一個(gè)新對(duì)象, 那么這個(gè)函數(shù)肯定具有prototype屬性。因?yàn)槲覀冏远x的函數(shù)都可通過(guò)new生成一個(gè)對(duì)象,所以我們自定義的函數(shù)都有prototype 這個(gè)屬性
// 函數(shù)字面量 console.log((function(){}).prototype); // {constructor: ƒ} // Date構(gòu)造器 console.log(Date.prototype); // {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …} // Math.abs 不是構(gòu)造器,不能通過(guò)new操作符生成一個(gè)新的對(duì)象,所以不含有prototype屬性 console.log(Math.abs.prototype); // undefined
prototype屬性有什么作用呢?作用就是:函數(shù)通過(guò)new生成的一個(gè)對(duì)象, 這個(gè)對(duì)象的原型(__proto__)指向該函數(shù)的prototype屬性:
// 其中F表示一個(gè)自定義的函數(shù)或者是含有prototype屬性的內(nèi)置函數(shù) new F().__proto__ === F.prototype // true // 通過(guò)函數(shù)字面量定義的函數(shù)的__proto__屬性都指向Function.prototype (function(){}).__proto__ === Function.prototype // true // 通過(guò)對(duì)象字面量定義的對(duì)象的__proto__屬性都是指向Object.prototype ({}).__proto__ === Object.prototype // true // Object函數(shù)的原型的__proto__屬性指向null Object.prototype.__proto__ === null // true // 因?yàn)镕unction本身也是一個(gè)函數(shù),所以Function函數(shù)的__proto__屬性指向它自身的prototype Function.__proto__ === Function.prototype // true // 因?yàn)镕unction的prototype是一個(gè)對(duì)象,所以Function.prototype的__proto__屬性指向Object.prototype Function.prototype.__proto__ === Object.prototype // true
constructor
constructor表示一個(gè)對(duì)象的構(gòu)造函數(shù),除null和undefined,JS中的所有數(shù)據(jù)類型都有這個(gè)屬性; 我們可通過(guò)下面的代碼來(lái)驗(yàn)證一下:
null.constructor // Uncaught TypeError: Cannot read property 'constructor' of null ... undefined.constructor // Uncaught TypeError: Cannot read property 'constructor' of undefined ... (true).constructor // ƒ Boolean() { [native code] } (1).constructor // ƒ Number() { [native code] } "hello".constructor // ƒ String() { [native code] }
一個(gè)對(duì)象的constructor屬性確切地說(shuō)并不是存在這個(gè)對(duì)象上面的; 而是存在這個(gè)對(duì)象的原型上(如果是多級(jí)繼承需手動(dòng)修改原型的constructor屬性),我們可用下面的代碼來(lái)解釋一下:
const F = function() {}; // 當(dāng)我們定義一個(gè)函數(shù)的時(shí)候,這個(gè)函數(shù)的prototype屬性上面的constructor屬性指向自己本身 F.prototype.constructor === F; // true
對(duì)JS的原始類型(string, number, boolean, null, undefined, symbol (new in ECMAScript 2015)),它們的constructor屬性是只讀的,不可修改:
(1).constructor = "something"; console.log((1).constructor); // 輸出 ƒ Number() { [native code] }
如果真想改這些原始類型的constructor屬性,也不是不可以:
Number.prototype.constructor = "number constructor"; (1).constructor = 1; console.log((1).constructor); // 輸出 number constructor
當(dāng)然上面的方式不推薦
以上所述是小編給大家介紹的JS原型和繼承詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)億速云網(wǎng)站的支持!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。