对象

1. 概述:
对象是 JavaScript 的基本数据类型, 它是一种复合值, 将很多值聚合在一起, 可通过名字访问这些值. 对象也可看做是属性的无序集合, 每个属性都是一个名/值对. 属性名是字符串, 因此可把对象看出是从字符串到值的映射. 在 ES5 中, 属性名可以不加引号.

2. 创建对象
(1) 对象直接量: 使用花括号 { } 把所有的属性括起来, 不同的属性之间用逗号","分割开, 最后一个属性不需要逗号. 属性名在前, 用冒号":" 在后面因此属性值. 当 { } 里面为空时表示此对象没有任何属性, 像如下代码中的 hsl. 对象可以嵌套, 把一个对象作为其中一个属性的值, 如下的 data 中含属性 metadata, 而 metadata 的值又是另外一个对象, 里面包含3个属性, 分别是 version、type 和 generator. version 与 type, type 与 generator 之间用逗号","分开, generator 后面不再需要了. var hsl = { }; var data = { metadata: { version: 4.5, type: 'Geometry', generator: 'Geometry.toJSON' } }; (2) new + 构造函数 var result = new Array( n ); var obj = new Object3D(); var axis = new Vector3(); var color = new Color(); var cameraPX = new PerspectiveCamera( fov, aspect, near, far ); (3) Object.create(): 第一个参数是对象的原型. 如果想创建一个普通的空对象, 传入Object.prototype 即可, 下面代码的前两行是等价的. var obj = new Object(); var obj2 = Object.create( Object.prototype ); var geometry = Object.create( this.constructor.prototype );

3. 对象的属性:
用点"."和方括号[]里面套入属性字符串名, 都可以访问属性和修改属性. var metadata = { version: 4.5, type: 'Geometry', generator: 'Geometry.toJSON' } console.log( metadata.version ); // 4.5 console.log( metadata["version"] ); // 4.5 metadata.version = 6.0; console.log( metadata.version ); // 6.0 使用["~"]这种形式有点像数组, 可称这种数组为散列映射字典. 当无法使用数字索引时, 它可帮上忙. 在 ES6 中, 使用 Map 会更好. var food = ['cake', 'ice-cream', 'candy']; var subjects = { s1: 'Math', s2: 'Music', s3: 'English' }; for(var i = 0; i < food.length; i++){ console.log( food[i], subjects['s' + (i+1)] ); } var obj = new Object(); function addAttributes(obj, name, value){ obj[name] = value; } addAttributes(obj, 'color', 'green'); addAttributes(obj, 'price', '¥10'); console.log( obj ); // Object { color: "green", price: "¥10" }

4. 遍历对象属性:
对象没有数组的 length 属性, 可通过 for in 来遍历对象里的每一个属性. var obj = { geometry: 'BoxGeometry', material: 'MeshBasicMaterial', object3D: 'Mesh' } for(var i in obj){ console.log( i + ': ' + obj[i] ); }

5. 检查属性:
可用in运算符、hasOwnProperty、!== 来检测对象是否含有这个属性, propertyIsEnumerable 是 hasOwnProperty 的增强版. 但当一个属性值本来就是 undefined 时, 只能用 in 来检测了. var obj = {x: 1}; console.log( 'x' in obj ); // true console.log( obj.hasOwnProperty('x') ); // true console.log( obj.propertyIsEnumerable('x') ); // true console.log( obj.x !== undefined ); // true

6. 增加属性:
加点运算符".", 然后在后面直接写上属性名, 再对它进行赋值即可. var subject = {}; subject.num = 2; subject.math = function(){ return "+ - × ÷ > = <"; }; subject.English = function() { return "a b c d e f g"; }; var s = subject; console.log( s.num ); console.log( s.math() ); console.log( s.English() );

7. 删除属性: delete
但delete只是断开对象和属性的联系, 并不会操作属性中的属性, 除非你把属性中的属性也 delete 了. var data = { metadata: { version: 4.5, type: 'Geometry', generator: 'Geometry.toJSON' } }; var m = data.metadata; delete m; console.log( data ); console.log( m.version ); // 4.5 delete m.version; console.log( m.version ); // undefined

8. getter 和 setter:
只含有 getter 的是只读属性, 只含有 setter 的是只写属性, 两者都包含的是读/写属性. objects: { get total() { return scope._objects.length; }, get inUse() { return this.total - scope.nCachedObjects_; } } x: { get: function () { return this._x; }, set: function ( value ) { this._x = value; this.onChangeCallback(); } }

9. 和变量的区别:
对象会在内存中分配一个空间, 而变量是没有的, 但能通过变量指引到内存空间里的地址, 来找到这个 对象. 如下代码的第一行 new Array(1, 2, 3, 4, 5) 即在内存中的某个位置创建了一个对象, 此对象的数据类型是数组, 但你不知如何访问. 第二行代码, 通过变量a能找到变量. 但是, 第一个和第二行的 new Array(1, 2, 3, 4, 5) 在内存中已经占了两个位置了, 是两个不同的对象, 虽然写出来的表示形式一样. 所以在数组中的6. 数组的比较, 不能通过表示形式一样, 就 判断两数组相等. new Array(1, 2, 3, 4, 5); var a = new Array(1, 2, 3, 4, 5);

10. 对象的长度:
Array有.length 属性, 但是Object没有, 可以通过 keys() 方法来提取键名, 从而转为一个数组, 再得到长度. 或者通过 hasOwnProperty( ) 来逐个计算长度. var obj = { position: {x:1, y:1}, size: {width:5, height:3}, color: 'blue' }; var arr = Object.keys(obj); console.log(arr); console.log(arr.length);