JavaScript的对象是一堆部属(property)的集合,每个部属是一个从名字到值的映射。从形式上,这构成了一种关联数组的形态。对象的部属可以是是另一个对象,这就构成了对象的嵌套,从而能让JavaScript表示复杂的数据结构。此外,对象还有类型之分。最基本的对象类型是"object"。
通过objectName.propertyName
可以引用对象objectName的propertyName部属。
通过var myCar = new Object();
的形式可以创建一个新的对象。这样创建出来的对象存在一些默认的部属,比如__proto__
(用来实现对象类型的延展)。虽然Javascript的类型系统中只有固定的几种类型,比如数值、字符串、对象、undefine、null等待。当时Javascript对象可以通过__proto__
标签给对象做标记,让对象具有不同的行为。这和C++等静态语言有一定的区别,C++的对象在创建时,其类型必须是已经确定的。Javascript则不然,可以在对象创建后通过修改__proto__
来达到修改自身行为的效果。这里的隐喻是:对象的行为是由其类型决定的。
JavaScript的对象部属有两个访问方式:myObject.hello
或者 myObject['hello']
。部属的名字可以事任意的可以转化为(调用Object.toString())字符串的值(空字符串也是一个合法的部属名)或者是Symbol类型。如果访问的部属在对象中没有定义,那么会返回undefined类型。比如打开一个浏览器,在其console中输入window.non_existing_prop
会返回undefined。
下面的代码会访问对象自身的部属:
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
console.log (`${i}, ${obj[i]}`)
}
}
上面的hasOwnProperty
会忽略那些从原型继承而来的属性。除了for...in
,还有下面两种办法:
Object.keys(o)
,返回一个自有的,可列举的部属名字列表Object.getOwnPropertyNames(o)
,除了可列举的部属以外,还会附加不可列举的部属
可以通过Object.getPrototypeOf
来回溯原型链,获取一个对象自身以及继承的所有部属。
删除一个部属,可以使用
delete myobj.a
这种语法
创建对象
可以从字面创建对象:
var obj = { a: 1, "b": 2}
var c="hello"
var obj2 = {c: 3, ...obj}
也可以通过构造函数创建:
function Elephant(trunk) {
this.trunk = trunk
this.whatType = function () { return this.type; }
}
// new 关键字用来给函数产生this变量
let elephant = new Elephant(20);
也可以使用Object.create
来创建对象,而不用通过构造函数。这个方法的特殊之处是,它可以通过:
Object.create(null)
a.__proto__ === undefined
a.hasOwnProperty === undefined
来创建没有原型的对象。参考Object.create(null)
访问控制
可以使用getter和setter来控制对某个部属的访问:
let o = { get hi() { return "hello" } }
o.hi // hello
也可以用Object.defineProperty
来创建,比如:
var d = Date.prototype;
Object.defineProperty(d, 'year', {
get: function() { return this.getFullYear(); },
set: function(y) { this.setFullYear(y); }
})
或者是Object.defineProperties
:
var o = { a: 0 };
Object.defineProperties(o, {
'b': { get: function() { return this.a + 1; } },
'c': { set: function(x) { this.a = x / 2; } }
});
其他
- HTML的forms对象是数组型对象,可以用三种形式访问:
document.forms[1] or document.forms["myForm"] or document.forms.myForm.
- Proxy可以重载对象的许多行为
- Working with Objects
- ES6 Reflection in Depth
- Proxy and Reflect
- Metaprogramming in ES6: Part 2 - Reflect
- Metaprogramming in ES6: Part 3 - Proxies
- ECMAScript 6: merging objects via Object.assign()
- Copying objects in Javascript
- WeakReferences TC39 proposal
- Weak references and finalizers
- AshleyScirra/via.js
- Proxy