一延柠、Object.defineProperty(obj, prop, descriptor);
定義或修改對象的一個(gè)屬性奏路,返回被定義的對象
數(shù)據(jù)描述符和存取描述符不能同時(shí)存在矮嫉,會產(chǎn)生異常
參數(shù):
- obj:需要定義屬性的目標(biāo)對象
- prop:屬性名稱
- descriptor:被定義或修改的屬性描述符
描述符:
configurable 定義該屬性的描述符是否可修改以及該屬性是否可 delete;
_通過 defineProperty 方法定義時(shí)默認(rèn)為 false口芍,顯示聲明賦值定義默認(rèn)為 true;
_若值為 false雇卷,除了writable 可以從 true 改為 false鬓椭, configurable,enumerable关划,writable小染,get,set 都不可再修改贮折;
// 默認(rèn)屬性都為 false裤翩,此時(shí) configurable 為 false,其他屬性都不可修改
var a = {};
Object.defineProperty(a, 'name', { value: 'june' });
Object.defineProperty(a, 'name', { configurable: true }); // TypeError: Cannot redefine property: name
Object.defineProperty(a, 'name', { enumerable: true }); // TypeError: Cannot redefine property: name
Object.defineProperty(a, 'name', { writable: true }); // TypeError: Cannot redefine property: name
Object.defineProperty(a, 'name', { value: 'july' }); // TypeError: Cannot redefine property: name
// configurable 位 false调榄,writable 可從 true 改為 false踊赠,但不可改回去
var a = {};
Object.defineProperty(a, 'name', { configurable: false, writable: true, value: 'june' });
console.log(a.name); // june
a.name = 'july';
console.log(a.name); // july
Object.defineProperty(a, 'name', { writable: false });
a.name = 'june';
console.log(a.name); // july
Object.defineProperty(a, 'name', { writable: true }); // TypeError: Cannot redefine property: name
enumerable 定義該屬性是否可被枚舉;
_通過 defineProperty 方法定義時(shí)默認(rèn)為 false每庆,顯示聲明賦值定義默認(rèn)為 true筐带;
_定義為 false 則不可在 for...in
和 Object.keys()
中被枚舉;
var a = {};
Object.defineProperty(a, 'name', { enumerable: true, value: 'june' });
Object.defineProperty(a, 'age', { enumerable: false, value: 17 });
console.log(a); // {name: "june", age: 17}
for(var i in a) {
console.log(a[i]);
}
// june
數(shù)據(jù)描述符(構(gòu)造器屬性)
writable 定義該屬性的值是否能被賦值操作改變缤灵;
_通過 defineProperty 方法定義時(shí)默認(rèn)為 false伦籍,顯示聲明賦值定義默認(rèn)為 true;
_定義為 false 后凤价,試圖重新復(fù)制會被忽略鸽斟,不會引發(fā)錯(cuò)誤;
value 定義該屬性的值
_默認(rèn)為 undefined
存取描述符(訪問器屬性)
get 給屬性提供的 getter 方法利诺;
_該方法的返回值被用作屬性值富蓄;
_默認(rèn)為 undefined;
set 給屬性提供的 setter 方法慢逾;
_該方法接收唯一參數(shù)立倍,并將改參數(shù)處理后的新值分配給該屬性灭红;
_默認(rèn)為 undefined;
function Obj() {
var _age = 17;
Object.defineProperty(this, 'dbAge', {
get: function() {
return _age;
},
set: function(newVal) {
_age = newVal * 2;
}
})
}
var obj = new Obj();
console.log(obj.dbAge); // 17
obj.dbAge = 10;
console.log(obj.dbAge); // 20
二口注、Object.defineProperties(obj, props);
批量定義一個(gè)對象的屬性变擒,返回被定義的對象
參數(shù):
- obj:需要定義屬性的目標(biāo)對象
- 定義屬性及其描述符的對象
兩種描述符的意思同上
三、Object.create(proto[, propertiesObject])
以指定對象為原型寝志,自定義屬性娇斑,創(chuàng)建一個(gè)新對象
返回新創(chuàng)建的對象
參數(shù)
- proto:新對象的原型對象
- propertiesObject:添加到新創(chuàng)建對象上的屬性及其描述符,寫法對應(yīng)
Object.defineProperties()
的第二個(gè)參數(shù)材部;
注意:
若 proto 參數(shù)不是一個(gè) null 或 Object毫缆,則拋出一個(gè) TypeError 異常
例子:
單式繼承:
function Shape() { // 父類
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};
function Rectangle() { // 子類
Shape.call(this); // 繼承父類實(shí)例屬性
this.z = 0;
}
Rectangle.prototype = Object.create(Shape.prototype, {
// 以父類原型對象為原型,新添加屬性乐导,創(chuàng)建對象
// 相當(dāng)于父類的空實(shí)例苦丁,再添加自定義屬性
// 將新創(chuàng)建的對象作為子類的原型對象
getRectangle: {
value: function() { console.log('i am getRectangle') },
configurable: true,
enumerable: false,
writable: true
}
});
// 修改子類原型對象的構(gòu)造函數(shù)指向
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
多個(gè)繼承:
function Sup1() {
this.sup1 = 'sup1';
}
function Sup2() {
this.sup2 = 'sup2';
}
function Sub() {
Sup1.call(this);
Sup2.call(this);
}
Sub.prototype = Object.create(Sup1.prototype);
// 此處是將第二個(gè)父類的原型屬性拷貝到子類原型對象,因?yàn)槭菧\拷貝物臂,故雖與第一個(gè)父類的繼承有點(diǎn)區(qū)別旺拉,但無傷大雅
Object.assign(Sub.prototype, Sup2.prototype);
Sub.prototype.constructor = Sub;
Sub.prototype.myMethod = function() {
// do some thing
}
Polyfill:
if(typeof Object.create !=="function") {
Object.create = function(proto, propertiesObject) {
if (typeof proto !=='object' && typeof proto !== 'function') {
throw new TypeError('Object prototype may only be an Object: ' + proto);
} else if (typeof proto === null) {
throw new Error("This browser's implementation of Object.create is a shim anddoesn't support 'null' as the first argument.")
}
function F() {};
F.prototype = proto;
return new F();
}
}
1