有关原型链与继承的相关知识,参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
创建对象
- 对象直接量 【建议使用】
var empty = {};
var point = { x: 0, y: 1} ;
var point2 = { x: point.x, y: point.y };
- 通过new创建并初始化一个新对象
var o = new Object();
var arr = new Array();
- 用自定义构造函数来初始化新对象
function range(from, to) {
this.from = from;
this.to = to;
}
range.prototype = {
// ...
}
var r = range(1, 5);
- Object.create() 【原型继承法】
var o = Object.create(Object.prototype); // 等价于{} 和 new Object()
var o1 = Object.create({x: 1, y: 2});
属性的查询和设置
- 属性的查询
有两种方法
var book = { name: 'hhh', author: 'bee' };
var name = book.name;
var author = book['author']; // 注意[]写法,属性名必须加引号,因为其使用字符串值;若为变量,不加。
- 属性的设置
同上,有两种方法可以创建属性或给已有属性赋值
book.name = 'hi';
book['main title'] = 'ES5';
- 属性访问错误
查询不存在的属性不会报错(返回undefined),但查询一个不存在的对象会报错。null和undefined都没有属性。
book.subtitle; // undefined
book.subtitle.length // TypeError: Cannot read property 'length' of undefined
只有确定book和book.subtitle都是对象,才能直接写book.subtitle.length。
可利用&&运算符的“短路”行为,写出一种简练的方法来避免出错。
var len = book && book.subtitle && book.subtitle.length;
删除属性
delete运算符只能删除自有属性,不能删除继承属性。
已经删除的属性的引用依然存在:
a = {p: {x: 1}};
b = a.p;
delete a.p;
b.x // => 1
因此,在销毁对象时,要遍历属性中的属性,依次删除,避免造成内存泄漏。
delete不能删除那些可配置性为false的属性。某些内置对象的属性是不可配置的,如通过变量声明和函数声明创建的全局对象属性。
delete Object.prototype // false
var x = 1;
delete this.x; // false
function f() {}
delete this.f; // false
删除全局对象的可配置属性时:
this.x = 1;
delete x; // 非严格模式可用
delete this.x; // 严格模式必须加上对全局对象的引用
检测属性
- in运算符
检测对象的自有属性或继承属性中是否包含这个属性。
in运算符的左侧是属性名(字符串),右侧是对象。
var o = {x: 1}
"x" in o // true
"y" in o // false
"toString" in o // true
此外,可用"!=="判断一个属性是否是undefined:
o.x !== undefined // true
o.y !== undefined // false
o.toString !== undefined // true
但只有in可区分*不存在的属性*和*存在但值为undefined*的属性
- hasOwnProperty()
检测给定的名字是否是对象的自有属性。
o.hasOwnProperty("x") // true
o.hasOwnProperty("y") // false
o.hasOwnProperty("toString") // false
- propertyIsEnumerable()
检测这个属性是自有属性且是可枚举的。
var o = Object.create({y: 2});
o.x = 1;
o.propertyIsEnumerable("x") // true
o.propertyIsEnumerable("y") // false 【y是继承来的】
Object.prototype.propertyIsEnumerable("toString") // false 【不可枚举】
枚举属性
for/in循环
可用在循环体中遍历对象中所有可枚举的属性(包括自有和继承的)。Object.keys()
返回一个由对象中可枚举的自有属性的名称组成的数组。Object.getOwnPropertyNames()
返回对象的所有自有属性的名称。
var o = {x: 1, y: 2, z: 3};
o.propertyIsEnumerable(x); // true
for (var p in o) { console.log(p); } // x y z
Object.keys(o); // ["x", "y", "z"]
Object.getOwnPropertyNames(Array); // ["length", "name", "arguments", "caller", "prototype", "isArray", "from", "of"]
Object.getOwnPropertyNames(Function); // ["length", "name", "arguments", "caller", "prototype"]
属性getter和setter
属性的特性
属性包含一个名字和4个特性。4个特性分别是它的值、可写性、可枚举性、可配置性。存取器属性(不具有值特性和可写性,可写性由setter方法存在与否决定)的4个特性是读取、写入、可枚举性、可配置性。
ES5定义了一个名为“属性描述符”(property descriptor)的对象,代表那4个特性。
- Object.getOwnPropertyDescriptor()
获得某个对象特定属性的属性描述符。
Object.getOwnPropertyDescriptor({x: 1}, "x")
// {value: 1, writable: true, enumerable: true, configurable: true}
var random = {
get octet() { return Math.floor(Math.random() * 256); }
}
Object.getOwnPropertyDescriptor(random, "octet")
// {set: undefined, enumerable: true, configurable: true, get: ƒ}
要想获得继承属性的特性,需要遍历原型链,参照Object.getPrototypeOf()
- Object.defineProperty()
设置属性的特性。
var obj = {key: 'temp'};
Object.getOwnPropertyDescriptor(obj, "key");
// {value: "temp", writable: true, enumerable: true, configurable: true}
Object.defineProperty(obj, "key", {
enumerable: false,
configurable: false,
writable: false,
value: "static"
}); // {key: "static"}
Object.getOwnPropertyDescriptor(obj, "key");
// {value: "static", writable: false, enumerable: false, configurable: false}
对象的三个属性
原型属性
Object.getPrototypeOf()
__proto__
用以直接查询/设置对象的原型,但不推荐使用。
Object.prototype.isPrototypeOf()类属性
对象的类属性是一个字符串,用以表示对象的类型信息。
只有一种间接的方法可以查询:默认的toString()方法(继承自Object.prototype)。为了调用正确的(而不是被重写的)toString()版本,必须间接调用Function.call()方法。
var o = [1, 2];
Object.prototype.toString.call(o).slice(8, -1); // 'Array'
- 可扩展性
详见Object.isExtensible()
序列化对象
将对象的状态转换为字符串,也可将字符串还原为对象。
- JSON.stringify()
序列化对象 - JSON.parse()
还原
对象方法
- toString()
- toLocaleString()
- toJSON()
- valueOf()