web知识(一)

一.js中的事件委托是什么?

它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件
eg:
有三个同事预计会在周一收到快递。
为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。
现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。
前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。
这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
程序中:现有和新添加的dom都是有事件的。

为什么要使用事件委托:提高性能。
eg:
100个li,使用for循环,大大增加交互,每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了。
如果用事件委托,那么我们就可以只对它的父级(如果只有一个父级)这一个对象进行操作,这样我们就需要一个内存空间就够了,自然性能就会更好。
事件委托的原理:
事件委托是利用事件的冒泡原理来实现的,【何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件】。
eg:
div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,
有这样一个机制,那么我们给【最外面的div加点击事件】,那么里面的【ul,li,a做点击事件的时候,都会冒泡到最外层的div上】
,所以都会触发,这就是【事件委托,委托它们父级代为执行事件】。
新增加的dom,也就不需要循环添加,事件了,绑定在父级上进行处理。
使用父级绑定事件,如何规避父级触发事件呢?
Event对象提供了一个属性叫target,可以返回事件的目标节点,标准浏览器用ev.target,IE浏览器用event.srcElement,判断如果是子级则触发业务。
适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。
mouseover和mouseout虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易
focus,blur之类的,本身就没用冒泡的特性,自然就不能用事件委托了。

二.什么是Promise?
1.ES6?
ECMAScript 是 JavaScript 语言的国际标准,JavaScript 是 ECMAScript 的实现。ES6时其2015年发布的版本,ES6目标是,让js成为企业级开发语言。
2.Promise?
Promise是ES6提供用来传递异步操作的消息的对象。
简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。
3.下面代码创造了一个Promise实例。

const promise = new Promise(function(resolve, reject) {
// ... some code

if (/* 异步操作成功 */){
  resolve(value);
} else {
  reject(error);
}
});

【Promise构造函数接受一个函数】作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
【resolve函数】的作用是,将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
【reject函数】的作用是,将Promise对象的状态从“未完成”变为“失败”,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
【Promise实例】生成以后,可以用【then/catch方法】分别【指定resolved状态和rejected状态的回调函数】。

let promise = new Promise(function(resolve, reject) {
console.log("Promise");
resolve();
if(不满足业务条件){
reject()
}
});

promise.then(function() {
  console.log("resolved.");
}).catch(err => {
console.log('catch error')
});
console.log("Hi!"); // Promise // Hi! // resolved

上面代码中,Promise 新建后立即执行,所以首先输出的是Promise。然后,【then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行】,所以resolved最后输出。
4.runAsync

function runAsync(){
var p = new Promise(function(resolve, reject){
  //做一些异步操作
  setTimeout(function(){
    console.log("执行完成");
    resolve("随便什么数据");
  }, 2000);
});
  return p; 
}
runAsync()

5.问题:1.包装这么一个函数有什么用?2.resolve("随便什么数据")作用?
在我们包装好的函数最后,会return出Promise对象,也就是说,执行这个函数我们得到了一个Promise对象。还记得【Promise对象上有then、catch方法】吧?这就是强大之处了。
并且:【Promise的优势在于,可以在then方法中继续写Promise对象】并返回,然后继续调用then来进行回调操作
链式操作的用法
所以,从表面上看,Promise只是能够简化层层回调的写法,而实质上,【Promise的精髓是“状态”】。
用维护状态、传递状态的方式来使得回调函数能够及时调用】,它比传递callback函数要简单、灵活的多。
所以使用Promise的正确场景是这样的:

runAsync1()
.then(function(data){
  console.log(data);
  return runAsync2();
})
.then(function(data){
  console.log(data);
  return runAsync3();
})
.then(function(data){
  console.log(data);
});

6.catch的用法
其实它和then的第二个参数一样,用来指定reject的回调,用法是这样:

getNumber()
.then(function(data){
  console.log("resolved");
  console.log(data);
})
.catch(function(reason){
  console.log("rejected");
  console.log(reason);
});

catch另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。
7.all的用法
Promise的all方法提供了【并行执行异步操作的能力】,并且在所有异步操作执行完后才执行回调

Promise.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
  console.log(results);
});

8.race的用法
all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」
9.promise对象特点:
(1)对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected

参考链接: https://www.cnblogs.com/liugang-vip/p/5616484.html;
参考链接: https://www.jianshu.com/p/063f7e490e9a;
参考链接: https://www.cnblogs.com/samve/p/10703953.html;

posted @ 2021-02-13 13:45  对月当歌  阅读(106)  评论(0)    收藏  举报