可迭代对象
是什么
可以使用for of
遍历的对象。对象内部包含一个返回迭代器(一个对象)的函数,迭代器通过实现next方法来遍历对象的属性。
实现的原理:迭代器
- 实现[Symblo.iterator]方法
- 该方法返回一个迭代器(iterator)
- 迭代器实现一个next方法
- next() 方法,返回一个包含两个属性的对象:
{value: 迭代的当前值, done: 一个布尔值,指示迭代是否完成}
手写原生迭代对象
const infos = {
name: "why",
age: 18,
height: 1.88,
[Symbol.iterator]: function() {
const entries = Object.entries(this)
let index = 0
// 这是一个迭代器
const iterator = {
next: function() {
if (index < entries.length) {
return { done: false, value: entries[index++] }
} else {
return { done: true }
}
}
}
return iterator
}
}
遍历方式一:使用迭代器的next方法
const iterator = infos[Symbol.iterator]()
console.log(iterator.next()) // {done: false, value: ['name', 'why']}
console.log(iterator.next()) // {done: false, value: ['age', ’18']}
console.log(iterator.next()) // {done: false, value: ['height', '1.88']}
console.log(iterator.next()) // {done: ture}
遍历方式二:for of
for (const item of infos) {
const [key, value] = item
console.log(key, value)
}
手写生成可迭代对象的构造函数
function Person(name, age, height, friends) {
this.name = name;
this.age = age;
this.height = height;
this.friends = friends;
// 实例方法
// this.running = function() {}
this[Symbol.iterator] = function() {
let index = 0;
//这是一个迭代器
const iterator = {
next: () => {
if (index < this.friends.length) {
return { done: false, value: this.friends[index++] };
} else {
return { done: true };
}
}
};
return iterator;
};
}
const p1 = new Person("why", 18, 1.88, ["curry", "kobe", "james", "tatumu"]);
const p2 = new Person("kobe", 30, 1.98, ["curry", "james", "aonier", "weide"]);
for (const item of p2) {
console.log(item);
}
js中内置的可迭代对象
- 数组: 实现了 Symbol.iterator,可以使用 for...of 遍历。
- 字符串: 字符串也是可迭代对象,允许逐个字符访问。
- Map 和 Set: 这两种集合类型也实现了迭代协议。
生成器
是什么
一个函数,本质上是[Symbol.iterator] () {}。调用该函数时,返回一个迭代器。该迭代器遍历的值为yield表达式。
如何使用
function* generatorFunction() {
yield '第一步';
yield '第二步';
yield '第三步';
}
const gen = generatorFunction();
console.log(gen.next()); // { value: '第一步', done: false }
console.log(gen.next()); // { value: '第二步', done: false }
console.log(gen.next()); // { value: '第三步', done: false }
console.log(gen.next()); // { value: undefined, done: true }
应用:实现斐波那契数列
function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a; // 生成当前值
[a, b] = [b, a + b]; // 更新到下一个值
}
}
const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3
console.log(fib.next().value); // 5
应用
- 处理流式数据(斐波那契数列)
- 循环控制
- 异步
异步的应用
promise
+ 生成器
结合使用
实例
// 模拟的异步操作:验证用户信息
function validateUser(user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user.username && user.password) {
resolve(user);
} else {
reject(new Error());
}
}, 1000);
});
}
// 模拟的异步操作:保存用户信息
function saveUser(user) {
return new Promise((resolve) => {
setTimeout(() => {
console.log("用户信息已保存:", user);
resolve(user);
}, 1000);
});
}
// 模拟的异步操作:发送欢迎邮件
function sendWelcomeEmail(user) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`欢迎邮件已发送给: ${user.username}`);
resolve();
}, 1000);
});
}
// 生成器函数
function* registerUser(user) {
try {
const validatedUser = yield validateUser(user);
const savedUser = yield saveUser(validatedUser);
yield sendWelcomeEmail(savedUser);
console.log("注册流程完成");
} catch (error) {
console.error(error.message);
}
}
// 执行生成器
function run(generator, user) {
const gen = generator(user);
function handle(result) {
if (result.done) return; // 结束
// result.value 是一个 Promise对象
result.value
.then((value) => {
handle(gen.next(value)); // 将结果传递给下一个 yield
})
.catch((error) => {
gen.throw(error); // 捕获错误
});
}
handle(gen.next()); // 启动生成器
}
// 示例用户
const newUser = {
username: "exampleUser",
password: "password123",
};
// 启动注册流程
run(registerUser, newUser);
但是,这样仍然复杂,可以使用async/await
进一步优化。
// 使用 async 函数处理注册流程
async function registerUser(user) {
try {
const validatedUser = await validateUser(user);
const savedUser = await saveUser(validatedUser);
await sendWelcomeEmail(savedUser);
console.log("注册流程完成");
} catch (error) {
console.error(error.message);
}
}
// 示例用户
const newUser = {
username: "exampleUser",
password: "password123",
};
// 启动注册流程
registerUser(newUser);
对比C++迭代器的实现原理
C++ 迭代器实现原理
C++ 迭代器的实现主要基于指针抽象
,依赖于存储的内存
是连续的。本质上是对指针的一种封装,提供一系列操作。比如,在 std::vector
中,迭代器的实现通常只是元素数组的一个指针,递增迭代器就等同于移动指针到数组的下一个元素位置。++it
实际上是指针自增,直接指向内存中下一个元素的地址。
js迭代器实现原理
JavaScript 的迭代器基于迭代协议。其实现不依赖底层内存地址,而是通过对象和方法来控制迭代过程。