原型属性(prototype)
对象的原型属性是用来继承属性的。在对象创建时原型属性就已经设置好了,(参考创建对象的方式)。
- 通过对象字面量创建的对象使用Object.prototype作为原型。
- 通过new创建的对象,使用构造函数的prototype属性作为原型。
- 通过Object.create()创建的对象使用第一个参数作为原型。其中参数可以为null。
查询对象原型
- ECMAScript5提供了Object.getPrototypeOf()方法查询对象的原型。
- ECMAScript3一般使用表达式对象.constructor.prototype来检测对象的原型。注意:此种方式并不可靠。
检测一个对象是否是另一个对象的原型
isPrototypeOf(),该方法的作用与instanceof运算符类似。
var o = {x: 1}
var p = Object.create(o)
o.isPrototypeOf(p) // true p继承自o
Object.prototype.isPrototypeOf(p) // true p继承自Object.prototype
// 下面是错误的继承方式
var p1 = {}
p1.prototype = o // 不起作用,不能给对象的prototype直接赋值
p1.x // undefined
o.isPrototypeOf(p1) // false p1没有继承o
类属性
对象的类属性是一个字符串,用以表示对象的类型信息。Object.prototype的toString()方法返回的格式如下:[object class],因此,可以通过对象的toString()方法提取类信息。但是,很多对象重写了toString()方法,因此可以间接调用Function的call方法,来获得类信息。
类型函数
function classof(o) {
if (o === null) return 'Null';
if (o === undefined) return 'Undefined';
return Object.prototype.toString.call(o).slice(8, -1);
}
classof(null) // 'Null'
classof(1) // 'Number'
classof(false) // 'Boolean'
classof([]) // 'Array'
classof({}) // 'Object'
classof(/^b/) // 'RegExp'
classof(new Date()) // 'Date'
function F() {}
classof(F) // 'Function'
classof(new F()) // 'Object'
可扩展性
对象的可扩展性用以表示是否可以给对象添加新属性。所有的内置对象和自定义对象都是可扩展的。ECMAScript5提供了查询和设置对象可扩展性的方法。通过Object.preventExtensions()可以将传入的对象转为不可扩展的,一旦对象转为不可扩展的,就无法将其再转为可扩展的。preventExtensions()只影响对象本身的属性添加,不会影响对象原型的扩展。
Object.esExtensible()
用来判断该对象是否可扩展的。
var o = {}
Object.isExtensible(o) // true
Object.preventExtensions()
用来将传入的对象转为不可扩展的。一旦对象转为不可扩展的,就无法将其再转为可扩展的。preventExtensions()只影响对象本身的属性添加,不会影响对象原型的扩展。
var o = {}
var p = Object.create(o)
var p1 = Object.preventExtensions(p) // 将参数对象返回
console.log(p1 === p) // true
p.x = 12 // 不起作用,因为p已转为不可扩展的
console.log(p.x) // undefined
o.y = 1
console.log(p.y) // 1 因为o是p的原型对象
Object.seal()
将对象锁定,不仅将对象转为不可扩展的,还将对象的自有属性设置为不可配置的。也就是说,对象不仅不能添加新属性,也不能删除属性,对象已有的可写属性仍然有效。对象的锁定操作也是不可逆的。可以使用Object.isSealed()来检测对象是否被锁定。
var o = {x: 1}
Object.isExtensible(o) // true 可扩展的
Object.getOwnPropertyDescriptor(o, 'x') // { value: 1, writable: true, enumerable: true, configurable: true }
Object.seal(o) // 锁定对象
Object.isSealed(o) // true
Object.isExtensible(o) // false 不可扩展的
Object.getOwnPropertyDescriptor(o, 'x') // x变为不可配置的 { value: 1, writable: true, enumerable: true, configurable: false }
delete o.x // false
o.x = 3 // x设置为3
console.log(o.x) // 3
Object.freeze()
对象冻结,不仅将对象设定为不可扩展、不可配置的还将对象自有属性的数据属性(非getter、setter属性)设置为只读的。该操作同样不可逆,可使用Object.isFrozen()来检测对象是否冻结。
var o = {x: 1}
Object.isExtensible(o) // true 可扩展的
Object.getOwnPropertyDescriptor(o, 'x') // { value: 1, writable: true, enumerable: true, configurable: true }
Object.freeze(o) // 冻结对象
Object.isFrozen(o) // true
Object.isSealed(o) // true
Object.isExtensible(o) // false 不可扩展的
Object.getOwnPropertyDescriptor(o, 'x') // x变为不可配置和不可写的 { value: 1, writable: false, enumerable: true, configurable: false }
delete o.x // false
o.x = 3 // 不起作用 x只读
console.log(o.x) // 1
Object.preventExtensions()、Object.seal()、Object.freeze()都返回传入的对象。
对象序列化
对象序列化指将对象的状态转换为字符串,也可将对象字符串还原为对象。JavaScript中可以通过JSON.stringify()和JSON.parse()来序列化和还原JavaScript对象。
var o = {
x: [1, 2, 3],
f: function() {},
z: {
a: 1
},
t: new Date()
}
var s = JSON.stringify(o) // 序列化
var p = JSON.parse(s) // 还原,p是o的深拷贝
console.log(p === o) // false
p.x.push(4) // x追加值4
console.log(o.x) // [1, 2, 3]
console.log(p.x) // [1, 2, 3, 4]
可以使用对象序列化来进行对象的深度复制。
网友评论