JavaScript的对象
JavaScript的对象就是一组名/值对的无序集合
const myObj = {
name: "John",
age: 30,
sayHello() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
};
for...in和for...of都是遍历对象的方法,这两种方法有什么区别呢?
书本上定义是这么说的:
for...in 循环用于遍历对象可枚举的属性,而 for...of 循环用于迭代可迭代对象的值
直接看定义有点抽象,不如先看两个例子:
// 使用 for...in 遍历对象的属性名
for (let propName in myObj) {
console.log(propName);
}
// 输出:
// name
// age
// sayHello
// 使用 for...of 遍历对象的属性值
for (let propValue of Object.values(myObj)) {
console.log(propValue);
}
// 输出:
// "John"
// 30
// function() {console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);}
从例子中可以看到,for...in遍历的是对象的属性,而且是可枚举的属性,for...of遍历的是对象的值,并且要求这个对象是可迭代的。
什么是可枚举?
可枚举是针对对象的属性来说的,JavaScript对象属性可分为数据属性和访问器属性,其中两种属性都有一个特性:enumerable,只要enumerable为ture,那么对象的这个属性就是可枚举的。
以下是一个JavaScript中数据属性的例子:
let obj = {};
// 定义一个名为"myProp"的数据属性
Object.defineProperty(obj, "myProp", {
value: "Hello, World!", // 属性值
writable: true, // 可写性
enumerable: true, // 可枚举性
configurable: true // 可配置性
});
以下是一个JavaScript中访问器属性的例子:
let obj = {
firstName: "John",
lastName: "Doe"
};
// 定义一个名为"fullName"的访问器属性
Object.defineProperty(obj, "fullName", {
get: function() {
return this.firstName + " " + this.lastName;
},
set: function(value) {
let names = value.split(" ");
this.firstName = names[0];
this.lastName = names[1];
},
enumerable: true,// 可枚举性
configurable: true
});
从上面的例子可知,obj的数据属性myProp和访问器属性fullName的特性enumerable都设置为ture,所以obj的myProp和fullName都是可迭代的,可以用for...in访问到。
什么是可迭代?
可迭代是针对对象的。一个对象只要实现了Iterator接口,那么这个对象就是可迭代的。
具体做法是实现对象的Symbol.iterator 方法,Symbol.iterator 方法应该返回一个迭代器对象,
这个迭代器对象应该至少实现一个 next() 方法,next() 方法返回一个对象,该对象应该至少包含以下两个属性:
- value:表示下一个元素的值。
- done:表示是否还有更多的元素需要迭代。如果迭代器已经迭代完所有元素,则返回 done:true。
const myArray = [1, 2, 3, 4, 5];
const myIterator = {
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < myArray.length) {
return { value: myArray[index++], done: false };
} else {
return { done: true };
}
}
}
}
}
for (const element of myIterator) {
console.log(element);
}
// 输出:
// 1
// 2
// 3
// 4
// 5
只要一个对象实现了Iterator接口,这个对象就是可迭代的,可以用for...of遍历这个对象的值。
JavaScript的数据类型中已经有自动实现Iterator接口的,它们是:
- 字符串(String)
- 数组(Array)
- TypedArray 对象(例如 Uint8Array 和 Float64Array)
- 类数组对象(例如 arguments 和 NodeList 对象)
- Map 对象
- Set 对象
- Generator 对象
但是也有两个数据类型没有实现Iterator接口,所以是不可迭代的:
- Symbol
- Object