- 数据属性
var person = {}
Object.defineProperty(person, 'name', {
configurable: true,//是否可配置,不指定时默认false,false表示不可配置,一旦指定false后delete被忽略且不能再修改writable之外的特性
enumrable: true,//是否可以用for-in枚举,默认false
writable: true,//是否可写,默认false时写入值会忽视或者报错(严格模式)
value: 'ari'//值
})
- 访问器属性
var book = {
_year: 2020,
edition: 1
}
Object.defineProperty(person, 'year', {
configurable: true,//是否可配置,不指定时默认false,false表示不可配置,一旦指定false后delete被忽略且不能再修改writable之外的特性
enumrable: true,//是否可以用for-in枚举,默认false
get: function(){return this._year},//只指定getter只读
set: funcion(value){//只指定setter只写
if(value>2020){
this.edition = value - 2020 + 1
this._year = year
}
}
})
- 指定多个属性 IE9+
var person = {}
Object.defineProperty(person, {
_year: {
value: 2020
},
year: {
configurable: true,//是否可配置,不指定时默认false,false表示不可配置,一旦指定false后delete被忽略且不能再修改writable之外的特性
enumrable: true,//是否可以用for-in枚举,默认false
get: function(){return this._year},//只指定getter只读
set: funcion(value){//只指定setter只写
if(value>2020){
this.edition = value - 2020 + 1
this._year = year
}
}
}
})
- 获取对象的属性的特性
var obj = ...
var des = Object.getOwnPropertyDescriptor(obj)
des.configurable
des.enumrable
typeof des.get //funtion
typeof des.set //funtion
-
创建对象的模式
工厂模式:函数中定义空对象,再添加属性和方法
构造函数:用new加函数,自动绑定对象到this,在this上添加属性和方法
构造函数直接调用时this总是指向Global对象 -
原型
创建新函数会自动创建其原型,函数的prototype属性指向原型,原型的constructor属性指向函数
原型的isPrototypeOf(实例对象)方法可以检查是否为对象原型
Object.getPrototypeOf(实例对象)可以获取原型
访问实例的属性会先查找对象自己的属性,再通过[[Prototype]]字段获取并查询查找原型上的属性
如果原型对象也有[[Prototype]]字段,会继续向上查找
原型本质是一个对象而不是每个实例一个对象,这样才能共享属性给所有实例,也会导致原型上的引用类型会被公用并且混淆
对象上的同名属性会覆盖原型,设置为null也会覆盖,因为属性访问顺序是先自身再原型,用delete可以删除属性解除覆盖
in操作符查询对象或其原型是否有某个字段: ‘属性’ in obj
实例从Object继承到的hasOwnProperty(‘属性’)可以确定是否为自身属性,跟in操作符结合和确定是否为原型属性
Object.keys(实例或原型)返回对象所有可枚举字段字符串数组,区分实例自身属性和原型上的属性
不想区分是否可枚举就用Oject.getOwnPropertyNames(实例或原型)
重写原型会导致原型指向Object,也可以手动指定contructor指向原函数
先new实例再重写原型会切断实例与新原型的关系,可以先重写原型再实例化,或者不要重写原型而是逐个指定方法或者属性
重写原生对象的原型可能导致命名冲突
自定义类型最经典的模式:构造函数与原型组合,即属性定义在构造函数内this上,方法定义在原型上
同时结合函数原型上是否有某个函数的判断,方法也可在函数内定义 -
继承
让原型对象等于另一个类型的实例,这个实例[[Prototype]]属性指向另一个原型(原型等于父函数实例)
未继承其他类型的函数的原型的[[Prototype]]默认指向Object
先用父类型实例替换原型,然后再重写子类型原型,会断开原型链
原型链继承的问题:
父类型实例的引用类型属性的共享和混淆,这些属性甚至是定义在父类型的this上的,父类型的多个实例不会共享,但是原型链继承是只有一个对象
创建子类型实例时不能像超类构造函数传参
组合继承或者叫伪经典继承:子类型借用超类函数传递参数,同时使用原型链继承超类属性方法
原型式继承:
function object(o){
function F(){};
F.prototype=0;
return new F();
}
缺点还是会共享引用类型
寄生组合继承 是最理想的继承范式:用到inheritePrototype方法和object方法,同时子类型中要借用超类构造函数
function inheritePrototype(subType,spuerType){
var prototype = object(superType.prototype);
prototype.constructor = subtype;
subtype.prototype = prototype;
}