ECMAScript6中的改變對象的原型

最初,在通過構(gòu)造函數(shù)Object.create()方法創(chuàng)建對象,其原型是在對象被創(chuàng)建時指定的,對象原型在實例化之后保持不變,ES5中出現(xiàn)了Object.getPrototypeOf()方法來返回任意指定對象的原型,但仍缺少對象在實例化后去修改原型的方法。

ES6中新增了Object.setPrototypeOf()來修改實例指向的原型對象。舉例:

let person = {
    name: 'zhangsan',
    get() {
        return this.name;
    }
}
let date = {
    time:new Date().getFullYear()+'年',
    get() {
        return this.time;
    }
}
let obj = Object.create(person);
let dt = Object.create(date);
const isAlong = Object.is(Object.getPrototypeOf(obj),person);

console.log(isAlong);  // true

console.log(obj.get()); //zhangsan

console.log(dt.get());  // 2021年

上述中先創(chuàng)建兩個基對象(person和date),通過兩個基對象去實例化,再去調(diào)取繼承對象的方法。
修改對象的原型

let person = {
    name: 'zhangsan',
    get() {
        return this.name;
    }
}
let date = {
    time:new Date().getFullYear()+'年',
    get() {
        return this.time;
    }
}
let obj = Object.create(person);
let dt = Object.create(date);

// 修改對象的原型
Object.setPrototypeOf(obj,date);  

const isAlong = Object.is(Object.getPrototypeOf(obj),person);
console.log(isAlong); // false
console.log(obj.get());  // 2021年
console.log(dt.get());  // 2021年
image.png

改變對象原型的原理:對象原型的真實值被儲存在內(nèi)部的一個特定的屬性[[Prototype]]中,調(diào)用Object.getPrototypeOf()方法返回儲存在其中的值,調(diào)用Object.setPrototypeOf()方法改變其中的值。

ES6中引入了Super引用的特性,使其更加快捷的訪問對象原型。

let person = {
    name: 'zhangsan',
    get() {
        return this.name;
    }
}

let common = {
    get(){
        return Object.getPrototypeOf(this).get.call(this) + 'common method'; // 修改對象原型
    }
}
let obj = Object.create(person);

Object.setPrototypeOf(common,obj);

console.log(common);
console.log(common.get()); // zhangsancommon method
const isAlong = Object.is(Object.getPrototypeOf(obj),person);
console.log(isAlong);  // true

在ES6中,還有一關(guān)鍵字super,super引用相當于指向?qū)ο笤偷闹羔?,實際上也就是等價于Object.setPrototypeOf(this)的值,可以簡化上述的get()方法

let common = {
    get(){
        return super.get() + 'common method'; // 修改對象原型
    }
}

注意點:super引用調(diào)用對象原型上所有其他的方法,必須要在使用簡寫方法的對象中使用super引用,但是如果在其他方法中聲明去使用就會報錯。
比如使用匿名函數(shù)定義一個屬性,由于上下文super引用不合法,則出現(xiàn)報錯

let common = {
    get:function(){
        return super.get() + 'common method';
    }
}
image.png

super引用在對于多重繼承的場景非常實用,不會像Object.getPrototypeOf(this).get.call(this)一樣引發(fā)沖突。

let person = {
    name: 'zhangsan',
    get() {
        return this.name;
    }
}

let common = {
    get(){
        return Object.getPrototypeOf(this).get.call(this) + ' common method';
    }
}

Object.setPrototypeOf(common,person);

let obj = Object.create(common);

console.log(Object.getPrototypeOf(obj));

console.log(obj.get());

image.png

由于this是obj,obj的原型是common對象,obj執(zhí)行common里面的get()方法時,Object.getPrototypeOf(this)這個返回的是common對象,這樣就導致了棧溢出報錯。
使用super更改代碼:

let person = {
    name: 'zhangsan',
    get() {
        return this.name;
    }
}

let common = {
    get(){
        return super.get() + ' common method';
    }
}

Object.setPrototypeOf(common,person);

let obj = Object.create(common);

console.log(Object.getPrototypeOf(obj));

console.log(obj.get());

super引用總是能指向正確的對象,因為多重繼承,對于super引用而言,始終指向的都是父級的對象,也就是person對象。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容