前端框架基础,打造你的前端应用。
箭头函数
使用箭头函数实现求多个数的和,可以有一个参数,也可以有多个或零个参数。
let sum = (...numbers) => {
return numbers.reduce((acc, curr) => acc + curr, 0);
};
let a=sum();
let b=sum(1);
let c=sum(1,2);
let d=sum(1,2,3,4,5);
let arr=[1,2,3,4,5,6];
let e=sum(...arr)
console.log(a, b, c, d, e)
// let sum=(...data)=>{
// s=0;
// for(let i=0;i<data.length;i++){
// s=s+data[i];
// }
// return s;
// }
可以安装nodejs与vscode的coderunner插件在vscode运行调试。
这里用了箭头函数的嵌套,其中(...参数)是一个rest参数,接着里面调用了reduce方法,回调函数是第一个参数,然后初始值0是第二个参数,注意看清楚逗号在哪,在js中经常有回调函数或箭头函数当参数的。
📚使用箭头函数要注意格式是:函数名=>函数的返回值。
📕如果没有参数就是()=》{},箭头函数不要再写return了,直接写值。然后一个参数名可以简写成参数=》{},两个或以上的则为一般形式(a,b,c,...)=>{}。
异步promise对象
红灯3秒亮一次,绿灯1秒亮一次,黄灯2秒亮一次;如何使用Promise让三个灯不断交替重复亮灯?,亮灯函数可以参考已经给出的或自行定义。
function red() {
console.log('red');
}
function green() {
console.log('green');
}
function yellow() {
console.log('yellow');
}
const run = (color, interval) => {
return new Promise((resolve) => {
setTimeout(() => {
color();
resolve();//使得 .then() 链中的下一个 Promise 被执行
}, interval)
})
}
//使用链式调用,依次的red,green,yellow,然后循环
const loop = () => {
Promise.resolve().then(() => {
return run(red, 3000);
}).then(() => {
return run(green, 1000);
}).then(() => {
return run(yellow, 2000);
}).then(() => {
loop()//递归调用
})
}
loop()
这里使用了链式调用,首先在run的创建promise里调用了resolve的,链式调用中从Promise.resolve().开始,确保 Promise 链的启动和顺序执行。然后每到一个then后面执行的run方法都会去执行resolve更换状态,即当前promise完成后才会进行.then进行下一个promise的执行,这里要理清楚。然后用了几个箭头函数嵌套,要注意看准符号进行拆分就好看懂了,根据题意,要实现异步,肯定得创建promise对象,然后传几个参数,有颜色也有时间间隔,接着看返回值,最后返回调用的肯定是计时器与具体的实现。
📚promise这里也有个常用的模板。new Promise((resolve,reject) => {}),resolve为成功状态的调用函数对应的具体实现为.then,reject为出现异常时的调用函数对应的具体实现为.catch。这个在前端中的使用还是比较重要的,在vue中后面的axios跨域也会用到。
然后,链式调用或许有点繁琐,也可以用es6中常用的异步方式async与await,当async函数内遇到await就会进行等待去处理await后跟的promise,没有加await直接执行。
function red() {
console.log('red');
}
function green() {
console.log('green');
}
function yellow() {
console.log('yellow');
}
// 创建一个延迟函数
function delay(interval) {
return new Promise(resolve => setTimeout(resolve, interval));
}
// 交替亮灯的函数
async function loop() {
while (true) {
red();
await delay(3000); // 红灯亮3秒
green();
await delay(1000); // 绿灯亮1秒
yellow();
await delay(2000); // 黄灯亮2秒
}
}
// 启动交通灯
loop();
可以看到,await里面执行的也是promise,因此要等前面的灯亮了才会执行后面的灯。
题变一下,js中如何实现程序并发执行,即如何实现3个灯各自同时并发执行?
const red = () => {
console.log('red');
};
const green = () => {
console.log('green');
};
const yellow = () => {
console.log('yellow');
};
// 用于控制灯光的显示
const run = (color, interval) => {
return new Promise((resolve) => {
setInterval(() => {
color(); // 每次调用灯光函数
}, interval);
});
};
const loop = () => {
Promise.all([
run(red, 3000), // 红灯每3秒亮一次
run(green, 1000), // 绿灯每1秒亮一次
run(yellow, 2000) // 黄灯每2秒亮一次
]);
};
loop();
把setTimeout改为setInterval,然后用Promise.all,进行全部的promise对象执行完,然后每个对象通过setInterval作间隔。
function red() {
console.log('red');
}
function green() {
console.log('green');
}
function yellow() {
console.log('yellow');
}
//定义一个异步函数来实现灯的调度
//这里只是每个颜色函数单独调用
async function asynf_run(color, interval) {
return await new Promise((resolve, reject) => {
setTimeout(() => {
color();
// console.log(new Date().toLocaleTimeString());//为了比对的方便,加入时间显示
asynf_run(color, interval);//重新执行函数,以达到循环的目的
}, interval);
})
}
//定义一个异步的函数,来执行并行的目的。
const parrallel = async () => {
asynf_run(red, 3000)
asynf_run(green, 1000)
asynf_run(yellow, 2000)
}
//主程序调用
parrallel();
也可以在async函数中不加入await则会执行并行操作,然后每个颜色相对应的promise对象是加了await异步的。
可以看到三个灯各自同时并发执行,间隔少的会打印多一点。
有小白可能觉得这个很难繁琐,那阁下要是按最简单的方法怎么做这道题,不用promise就得嵌套好几个setTimeout或setInterval了,写一下就会发现好像更繁琐难看懂,所以学一些新的框架语法对开发还是有用的。
Promise与async/await的区别
Promise: 返回一个 Promise 对象,使用.then() 和 .catch()方法来处理成功和失败的结果在多个嵌套的异步操作中,可能导致多个回调或难以阅读的链式调用。
async/await: 总是返回一个 Promise,即使它返回的是一个非 Promise 值。提高了代码的可读性,更接近于同步代码的风格,易于理解和维护。
箭头函数的this
📕箭头函数中this指向的规则是什么?
箭头函数中的this指向根据当前执行上下文的变化而变化,遵循谁调用就指向谁。没找到直接调用者,则this指的是全局对象window。在严格模式下,没有直接调用者的函数中的this是undefind。使用call,apply,bind绑定,this指的是绑定的对象。嵌套函数中的this不会继承外层函数的this值。
下面代码输出结果分别是什么?为什么?
student1 = {
name: '张三',
outerName(){
displayName=function(){
console.log('student1: '+this.name)
};
displayName();
}
}
student1.outerName();
student2 = {
name: '张三',
outerName(){
displayName= () => {
console.log('student2: '+this.name)
}
displayName();
}
}
student2.outerName();
分别是 student1: undefined 、 student2: 张三。
当student1.outerName() 被调用时,在 outerName 方法内部,displayName 被声明为一个普通函数。当 displayName() 被调用时,this 的值在这个上下文中是全局对象(在浏览器中是 window,在 Node.js 中是 global),而不是 student1。所以,this.name 是 undefined(除非在全局作用域中有一个 name 属性)。student2.outerName() 被调用。当student2.outerName() 被调用时,displayName 被声明为一个箭头函数。箭头函数不绑定自己的 this,它会捕获外部上下文中的 this 值。在这种情况下,this 指向的是 student2 对象。因为普通函数的 this 绑定与箭头函数的 this 绑定行为不同。
实验心得
谁来异步写个作业吧。