JavaScript 对象
对象 指包含数据和用于处理数据的指令的数据结构. 对象有时也指现实世界中的一些事, 例如在赛车游戏当中一辆车或者一幅地图都可以是对象。—— MDN
JavaScript 中的对象由和
组成。
可以是任意 JavaScript 中的数据类型,则是。
对象的格式如下:
{
prop1: 'value1',
prop2: ,
prop3: {},
method1: function() {
},
}
其中 prop1
、prop2
、prop3
都是,method1
是,是任意的数据类型,则是。
可以看到或者,在其名字与值中间采用冒号 :
分隔,和之间采用逗号 ,
分隔。
通常和的名字会被称为名
与名
,的值称为值
,的值则直接叫做 。
对象符合 key/value
的结构, key
对应 value
,这种结构也被称为键值对,名和名都是 key
,他们的值都是 value
。
注意:在 JavaScript 的对象中,和的表示其实是一样的。
的值如果是,则就把这个称之为,只是称呼上的不同。
对象最简单的创建方式就是使用对象字面量
。
var person = {};
以上创建了最简单的空对象。
对象在 JavaScript 中的应用范围非常广。
可以试想一下,如果需要用变量描述人的信息,名字、性别、年龄、双亲信息,同时就要表示这个人的一些行为,如说话。
显然数值、字符串、布尔类型这些数据类型是不太适合描述这样人的。
这个时候就可以考虑使用对象,也就是说当需要描述的事物变得复合(无法使用单一的数据类型描述的时候),就可以考虑使用对象存储数据。
var person = {
'name': '小明',
'age': ,
isAdult: false,
sex: 'man',
hobby: ['eat', 'sleep', 'play doudou'],
parents: {
mather: {
name: '大红',
},
father: {
name: '大明',
},
},
say: function() {
console.log('我叫' + this.name + ',我今年' + this.age + '岁了。');
},
};
console.log(person); // 在控制台可以观察 person 对象
上面这个 person
变量就是对象,用于描述人,这个人具有 name
、age
等与。
在控制台对象后,可以对其展开,观察他的。
其中部分在声明的时候,名上了引号,这在 JavaScript 中是被允许的,但一般情况下不会引号,原因之一是没有必要加,不应该与字符串混淆,另外一点就是可以消除初学者对 JSON 和 JavaScript 对象在理解上的歧义。
创建对象主要是为了设置、访问对象的值,对象的等。
访问有 2 种方式:
var obj = {
key: 'value',
say: function() {
console.log('never 996');
},
};
console.log(obj.key); // :"value"
console.log(obj['key']); // :"value"
obj.say(); // :"never 996"
obj['say'](); // :"never 996"
这两种方式都很常用。第二种通常会应用在需要用变量确定名的时候去使用。
var person = {
age: ,
name: '鸽手',
};
Object.keys(person).forEach(function(key) {
console.log(person[key]);
});
以上就是使用第二种方式的场景之一,使用 Object.keys()
到 person 的所有名组成的数组,对数组做遍历拿到每名并放在变量中,再通过变量访问到对应的值。
当试图访问不存在的的时候,则会返回 undefined
。
var obj = {};
console.log(obj.value); // :undefined
设置值也有 2 种方式:
设置值的方式与访问值很相似,只是多了赋值操作。
设置值按照如下规则进行:
var person = {
age: ,
};
person.name = '阿花';
person['hobby'] = ['eat', 'play doudou'];
console.log(person);
person.age = ;
console.log(person);
对象的名是可以用任意字符串表示的。
上面有提到,声明的时候可以带上引号。
如果不带引号,那名必须要符合变量命名的规则,使用引号包裹名,则可以使用任意字符串作为名。
var obj = {
--^$@@@age: ,
};
上面这样写是会报错的,如果非要使用这样的名,就可以一对引号,可以双引号,也可以是单引号,使用引号的规则和字符串一致。
var obj = {
'--^$@@@age': ,
};
这种特殊的名无法通过 对象.名
的形式访问。
var obj = {
'--^$@@@age': ,
};
var val = obj.--^$@@@age;
JavaScript 无法解析这种特殊的语法,所以要使用 对象['名']
的形式访问。
var obj = {
'--^$@@@age': ,
};
var val = obj['--^$@@@age'];
console.log(val); // :16
特殊的名场景比较少,如的场景。
var counter = {};
var strs = [
'#@T%TGFDSgfdsgsf',
'#@T%TGFDSgfdsgsf',
'123fdafeafewa',
'123fdafeafewa',
'#@T%TGFDSgfdsgsf',
];
strs.forEach(function(item) {
if (item in counter) {
counter[item]++;
} else {
counter[item] = ;
}
});
console.log(counter);
strs 是由字符串组成的数组,即需要的一组数据。
利用对象的特性来对字符串计数。
除了字面量的方式,还有许多创建对象的方式。
使用 new Object()
或者 Object()
的方式也可以创建对象
var obj1 = new Object();
var obj2 = new Object; // 如果没有参数 可以不带括号
var obj3 = Object();
上面的方式都可以创建空对象。
比较有趣的是可以给 Object
传递对象字面量作为参数,返回的对象的与传入的对象字面量的一致。
var obj1 = new Object({
age: ,
name: '长睫毛',
});
var obj2 = Object({
age: ,
name: '小酒窝',
});
console.log(obj1, obj2);
使用构造,也可以创建对象。
function Car(color, maxSpeed) {
this.color = color;
this.maxSpeed = maxSpeed;
}
Car.prototype.bibi = function() {
console.log('哔哔!');
};
var car = new Car('red', );
console.log(car);
以上例子使用构造创建了速度超级快的车
对象。
使用 Object.create
也可以创建新对象,但是必须传递对象作为参数。
var parent = {
walk: function() {
console.log('走路');
},
};
var son = Object.create(parent);
console.log(parent === son);
son.walk();
Object.create
会根据传递过去的对象新的对象,作为参数传递的对象会作为新对象的原型。
var me = {height: , weight: };
var i;
for (i in me) {
console.log(i);
console.log(me[i]);
}
使用 for ... in
可以遍历对象的所有 key 值,也就是名,取到所有的就可以访问到所有的值。
需要注意的是 for ... in
循环只遍历可枚举,同时对象原型上的也会被访问到。
var me = {height: , weight: };
var you = Object.create(me);
you.age = ;
var i;
for (i in you) {
console.log(i);
}
上面这个例子就把 me
和 you
中的所有都遍历出来了。
可以使用 Object.prototype.hasOwnProperty
来判断是否只处于其本身而不在原型上。
var me = {height: , weight: };
var you = Object.create(me);
you.age = ;
var i;
for (i in you) {
if (you.hasOwnProperty(i)) {
console.log(i);
}
}
这样就只会 age
了。
Object.keys
会返回对象上的所有可枚举组成的数组。
var gugugu = {
name: '?王',
hobby: '放鸽子',
};
var keys = Object.keys(gugugu);
console.log(keys);
keys.forEach(function(key) {
console.log(gugugu[key])
});
通过遍历组成的数组来遍历对象。
使用 Object.getOwnPropertyNames
也可以到由组成的数组,但数组会不可枚举的。
var gugugu = {
name: '?王',
hobby: '放鸽子',
};
var desc = Object.create(null);
desc.enumerable = false; // 是否可枚举 认就是false
desc.value = '最强鸽手';
Object.defineProperty(gugugu, 'nickname', desc);
console.log(Object.keys(gugugu));
console.log(Object.getOwnPropertyNames(gugugu));
使用 getOwnPropertyNames
比使用 keys
多出不可枚举的 nickname
。
注意:ES6 还提供了Object.values
、Object.entries
、for ... of
、Reflect.ownKeys
等特性,结合这些特性也能遍历对象。
纯净对象仅为本篇中的称呼方式,这种特殊的对象没有特定的称呼。
纯净对象即原型为 null 的对象。
使用 Object.create(null)
来创建纯净对象。
var obj1 = Object.create(null);
console.log(obj1);
var obj2 = {};
console.log(obj2);
可以尝试在控制台中对比这两个对象,纯净对象是没有原型的,无法 toString
、hasOwnProperty
、valueOf
这些原型上的。
大部分使用纯净对象的场景是使用 Object.defineProperty
为的时候,的描述需要绝对干净的对象,防止特殊的对描述造成影响。
另外的使用场景就是当作字典使用,防止原型上的对字典产生干扰。
对象最常用的两种创建方式,就是使用字面量和构造。
创建对象的时候应合理规划名和名,根据业务来确定如何使用对象。