【笔记】再学JavaScript ES(6-10)全版本语法——Generator(案例:抽奖&斐波那契数列)
2023-09-27 14:26:51 时间
Generator(生成器)
1.引入案例:让遍历停下来
ES5
function loop () {
for (let i = 0; i < 5; i++) {
console.log(i)
}
}
loop()
ES6
function * loop () {
for (let i = 0; i < 5; i++) {
yield console.log(i)
}
}
const l = loop()
l.next()
l.next()
l.next()
2.Next
- Generator函数函数名之前需要加
*
- 在需要控制的语句前加 yield
- 可嵌套使用
- Generator对象调用next函数来执行被控制的语句,执行时返回yield后面表达式的返回值和Generator对象执行状态
function * f () {
yield console.log(1)
yield console.log(2)
let val
console.log(val = yield [1, 2, 3]) // val,将整个yield表达式的值替换为next的参数
console.log(yield val) // 10,整个yield表达式的值,即传给next的参数
}
const l = f()
console.log(l.next(10)) // {value: undefined, done: false} 第一个yield后面表达式的返回值
console.log(l.next(10)) // {value: undefined, done: false} 第二个yield后面表达式的返回值
console.log(l.next(10)) // {value: Array(3), done: false} 第三个yield后面表达式的返回值
console.log(l.next({ 'A': 'a', 'B': 'b' })) // {value: {A: "a", B: "b"}, done: false} 将参数传递给整个yield表达式并完成
console.log(l.next(10)) // {value: undefined, done: true}
/**
* 只有当整个Generator函数执行完毕(最后一个yield执行完毕),状态done才会置为true(其实返回的是上一个next执行完后的状态)
*/
3.Return
function * f () {
yield console.log(1) // 1
yield console.log(2)
let val
console.log(val = yield [1, 2, 3])
console.log(yield val)
}
const l = f()
console.log(l.next('next')) // {value: undefined, done: false}
console.log(l.return('return')) // {value: "return", done: true}, 类似return关键字,参数直接影响最终return函数的返回值
4.Throw
function * f () {
try {
yield console.log(1) // 1
yield console.log(2)
yield console.log(3)
} catch (e) {
console.log(e.message) // throw
} finally {
let val
console.log(val = yield [1, 2, 3]) // yield表达式的值——next的参数‘next’
console.log(yield val) // yield表达式的值——next的参数‘next’
}
}
const l = f()
console.log(l.next('next')) // {value: undefined, done: false}
console.log(l.throw(new Error('throw'))) // {value: Array(3), done: false},如果所执行代码外没有try catch就抛出异常,报错,直接中断
console.log(l.next('next')) // {value: "next", done: false},返回值为yield表达式的值——next的参数‘next’
console.log(l.next('next')) // {value: undefined, done: true}yield表达式的值——undefined
5.案例:抽奖
ES5
function draw (first = 1, second = 3, third = 5) {
let firstPrize = ['1A', '1B', '1C', '1D', '1E']
let secondPrize = ['2A', '2B', '2C', '2D', '2E', '2F', '2G', '2H', '2I', '2J']
let thirdPrize = ['3A', '3B', '3C', '3D', '3E', '3F', '3G', '3H', '3I', '3J', '3K', '3L', '3M', '3N', '3O', '3P']
let result = []
let random
// 抽一等奖
for (let i = 0; i < first; i++) {
random = Math.floor(Math.random() * firstPrize.length)
// 使用concat合并数组,使用splice删除数组中选中的元素并返回被删除的元素合并到result数组中
result = result.concat(firstPrize.splice(random, 1))
}
// 抽二等奖
for (let i = 0; i < second; i++) {
random = Math.floor(Math.random() * secondPrize.length)
// 使用concat合并数组,使用splice删除数组中选中的元素并返回被删除的元素合并到result数组中
result = result.concat(secondPrize.splice(random, 1))
}
// 抽三等奖
for (let i = 0; i < third; i++) {
random = Math.floor(Math.random() * thirdPrize.length)
// 使用concat合并数组,使用splice删除数组中选中的元素并返回被删除的元素合并到result数组中
result = result.concat(thirdPrize.splice(random, 1))
}
return result
}
let t = draw()
for (let value of t) {
console.log(value)
}
ES6
function * draw (first = 1, second = 3, third = 5) {
let firstPrize = ['1A', '1B', '1C', '1D', '1E']
let secondPrize = ['2A', '2B', '2C', '2D', '2E', '2F', '2G', '2H', '2I', '2J']
let thirdPrize = ['3A', '3B', '3C', '3D', '3E', '3F', '3G', '3H', '3I', '3J', '3K', '3L', '3M', '3N', '3O', '3P']
let count = 0 // 控制抽奖人数
let random
while (1) {
if (count < first) {
random = Math.floor(Math.random() * firstPrize.length)
yield firstPrize[random] // 被抽中的人选
count++
firstPrize.splice(random, 1) // 去掉被抽中的人,防止重复
} else if (count < first + second) {
random = Math.floor(Math.random() * secondPrize.length)
yield secondPrize[random] // 被抽中的人选
count++
secondPrize.splice(random, 1) // 去掉被抽中的人,防止重复
} else if(count < first + second + third) {
random = Math.floor(Math.random() * thirdPrize.length)
yield thirdPrize[random] // 被抽中的人选
count++
thirdPrize.splice(random, 1) // 去掉被抽中的人,防止重复
} else {
console.log('本轮抽奖结束')
return false
}
}
}
let t = draw()
console.log('下面输出一等奖名单:')
console.log(t.next().value)
console.log('下面输出二等奖名单:')
console.log(t.next().value)
console.log(t.next().value)
console.log(t.next().value)
console.log('下面输出三等奖名单:')
console.log(t.next().value)
console.log(t.next().value)
console.log(t.next().value)
console.log(t.next().value)
console.log(t.next().value)
console.log(t.next().value)
6.案例:用Generator实现一个斐波那契数列
function * f () {
let sum1 = 0
let sum2 = 1
yield sum1
yield sum2
while (1) {
yield sum1 = sum1 + sum2;
[sum1, sum2] = [sum2, sum1] // sum1 = [sum2, sum2 = sum1][0] // 交换
}
}
let l = f()
for (let i = 0; i < 12; i++) {
console.log(l.next().value)
}
拓展:
相关文章
- Javascript中的循环变量声明,到底应该放在哪儿?
- 【笔记】再学JavaScript ES(6-10)全版本语法——ES8新增
- 【笔记】再学JavaScript ES(6-10)全版本语法——Proxy代理
- 【笔记】再学JavaScript ES(6-10)全版本语法——参数、箭头函数
- 【笔记】再学JavaScript ES(6-10)全版本语法——Class
- 【笔记】再学JavaScript ES(6-10)全版本语法——Array(遍历、转换、创建、查找)
- 【笔记】再学JavaScript ES(6-10)全版本语法——课程介绍与环境搭建
- JavaScript(JS) Math.random()
- JavaScript(JS) string.link( hrefname )
- JavaScript 炫酷第一步 抓取别人网站数据
- 微软的 ES 类型语法提案对 JavaScript 意味着什么
- 利用javascript的面向对象的特性实现限制试用期
- JavaScript原型详解