前端开发进阶——ES6

ES6

1.Promise

Promise是ES6实现异步编程的一种方式

3种状态:pending进行中,fulfilled 已成功,rejected 已失败

2种状态的改变 :pending->fulfilled, pending->rejected

状态一旦改变就不能再变

Promise构造器,会传入一个函数,这个函数的参数是resolve,reject,它们是由js引擎提供的函数。resolve 负责将promise的状态由pending 变为fulfilled, 在异步操作成功时调用,并将异步操作的结果作为参数传递出去。reject将promise的状态由pending 变为rejected, 在异步操作失败时调用,并将异步操作的结果作为参数传递出去。

then 回调,有两个参数,第一个参数指定当Promise的状态变为resolved时的回调函数,是必须的,第二个参数指定当Promise的状态变为rejected时的回调函数,是可选的。

catch 用于指定当异步操作发生错误,变为rejected状态时的回调函数

all 并行异步,Promise.all([promise1,promise2,...]).then(),只有当参数内所有promise都变为resolved时,才会执行then回调,如果有一个为rejected,则回调失败,失败原因是第一个promise失败的原因。

注意:

  • 无论是then(),还是catch(), 默认返回值都会被放入promise的resolve里面
  • new Promise() 会立即执行,与resolve() 和 reject() 位置无关,then catch回调进入微任务队列
  • Promise里如果不调用resolve或reject,就会一直处于Pending状态,then和catch也不会执行
定义:
写法1
new Promise(function(resolve,reject){
resolve(data)  或 return data; 正常执行 
reject(error); 或 throw error; 发生错误
}).then( ()=>{
    //resolve回调函数
}, ()=>{
    //reject回调函数
})
写法2
new Promise(function(resolve,reject){
resolve()  正常执行
reject(); 或 throw “error”; 发生错误
}).then( ()=>{
    //resolve回调函数
}).catch(()=>{
    //reject回调函数
})

.catch(function(value){    
console.log(value);
return new Promise(function(resolve){
	resolve(123);
});
})
等价于
.catch(function(value){    
console.log(value);
return 123;
})
let p = new Promise(function(resolve,reject){
            reject(5)
        }).then(()=>{
            throw 'error';
        },()=>{
            console.log('position 1');
            return "123"
        }).catch((data)=>{
//           console.log('position 2',data)
            return data;
        }).then((value)=>{
            console.log('last',value)
        });
输出:position 1
      last 123
let p = new Promise(function(resolve,reject){
            console.log("start");
            reject();
        }).then(()=>{
            console.log("then1");
            throw 'error';
        },()=>{
            console.log('position 1');
            return "123"
        }).catch((data)=>{
            console.log('position 2',data)
            return data;
        }).then((value)=>{
            console.log('last',value)
        });
// 输出:start
        position 1 
	last 123
Promise 代码实现
const PENDING=”PENDING”;
const FULFILLED =”FULFILLED”;
const REJECTED=”REJECTED”;
class myPromise{
	constructor(){
		this.state=PENDING;
		this.value=undefined;  // 成功传值
		this.reason=undefined;  // 错误原因
		this.successCB=[];   //成功存放的数组
		this.failCH=[];   // 失败存放的数组
		let resolve=function(value){
			if(this.state===PENDING){
				this.state=FULFILLED;
				this.value=value;
				this.successCB.forEach(f=>f());
			}
		}
	}
	let reject=function(err){
		if(this.state===PENDING){
				this.state=REJECTED;
				this.reason=err;
				this.failCB.forEach(f=>f());
		}
	}
	try{
		executor(resolve,reject);  //立即执行函数
	}catch(e){
		reject(e);
	}
	then(onFulfilled,onRejected){
		if(this.state=FULFILLED){
				onFulfilled(this.value);
		}else if(this.state=REJECTED){
		onRejected(this.reason);
		}else if(this.state=PENDING){
		this.successCB.push(onFulfilled(this.value));
		this.failCB.push(onRejected(this.reason));
		}
	}
}
Promise.all=function(promises){   //输入Promises数组
	var count=0;
	var list=[];
	funtion handle(i,data){
		count++;
		list.push(data);
		if(count==promies.length){
				resolve(list);
		}
	}
	return new Promise((resolve,reject)=>{
		for(let i=0;i<promises.length;i++){
				promises[i].then(res=>handle(i,res),error=>reject(error));
		}
	})
	}

2. async VS await

async 将修饰的函数变为一个异步函数,它只是对返回值进行了包装,无论如何都会返回一个promise,本质还是一个函数需要调用才能执行。如果不加await它与Promise是一样的

async function aa(){
   return "hello";
}

aa().then((res)=>{
  console.log(res);    //hello
})

执行顺序问题(常考)

async 遇到await 会阻塞当前代码,先执行await中的同步代码,再跳出async执行主线程内的同步代码,最后再返回async继续向下执行,同步代码执行完后,再执行微任务队列,宏任务队列。

async function async1() {
    console.log( '1' )
    console.log(await async2())
    console.log( '2' )
}

async function async2() {
    console.log('3')
    setTimeout(
      ()=>console.log('4')
    ,0)
    console.log( '5' )
}

console.log( '6' )
setTimeout( function () {
    console.log( '7' )
}, 0 )
async1();
new Promise( function ( resolve ) {
    console.log( '8' )
    resolve();
} ).then( function () {
    console.log( '9' )
} )
console.log( '10' )


// 6 1 3 5 8 10 2  9(微任务)  7 4 (宏任务)
// 微任务清空,选择第一个宏任务执行,再检查微任务队列。。依次循环

3. 宏任务 VS 微任务

宏任务:script代码,UI渲染,setTimeout/setInterval ajax 鼠标键盘等事件

微任务:process.nextTick  promises  Object.observe  MutationObserver

执行顺序:宏任务和他所产生的微任务是绑定的,一个宏任务执行完成后,这个宏任务所产生的微任务,以及微任务产生的微任务全部执行完后。才会执行下一个宏任务。在执行下一个宏任务之前,就会进行页面渲染。

4. 变量提升

对变量进行提升,只声明,不赋值,值为undefined

var v='Hello World';

(function(){

    alert(v);   // undefined

    var v='I love you';

})()

不只变量,函数的声明式也可以提升,但是函数表达式和箭头函数不能提升。

5. var let const

  • var可以变量提升,但let const不可以
  • var 只有全局作用域与局部作用域,但let const除了全局局部外,还有块级作用域
  • var let 定义的是变量,const 定义的是常量,也就是说其值是不可以改变的,但是对于const类型的对象来说,只是对象的地址不可以改变,对象内容是可以改变的
  • var 允许重复声明变量,但let const不允许
  • let const 是ES6后才支持的语法
  • const具有let所有特性,但是它式不可改变的,(const修饰对象,可以改变对象的值)

6. 事件捕获与事件冒泡

事件捕获:自上而下触发

事件冒泡:自下而上触发 e.stopPropagation() 阻止事件冒泡  

addEventListener,第三个参数为true,则是事件捕获,false(默认)为事件冒泡

<div id="parent">
<div id="child" class="child"></div>
</div>

doucument.getElementById(“parent”).addEventListener(“click”,function(){
alert(“parent”);
},true)

doucument.getElementById(“child”).addEventListener(“click”,function(){
alert(“child”);
},true)

7. 事件委托(事件代理)

利用事件冒泡的原理,将本应该注册在子元素上的处理事件注册到父元素上,这样当我们点击子元素时,发现子元素没有对应的事件就会自动到父元素上寻找做出响应。

好处:1.减少DOM操作,优化性能。2. 动态添加的子元素也会有相应的事件。3. 减少事件注册,节省内存空间

parent.addEventListener(“click”,function(event){
    var e= event|| window.event;
    var target=e.target;
    if(target.id===”child1”){   }
})

8. JS设计模式

(1)单例模式,一个类只能有一个对象实例

var single=(function(){
    var instance=null;
    function Single(name){
        this.name=name;
    }
    return function(name){
        if(!instance){
            instance=new Single(name);
        }
        return instance;
    }

})();

(2)工厂模式,代替 new 来创建对象,批量制作属性相同的对象实例(指向不同)

function Animal(o) {
      var instance = new Object()
      instance.name = o.name
      instance.age = o.age
      instance.getAnimal = function () {
        return "name:" + instance.name + " age:" + instance.age
      }
      return instance
}

var cat = Animal({name:"cat", age:3})
console.log(cat);

(3)构造器模式  使用构造方法创建对象

  (4)发布-订阅者模式(观察者模式)

             发布者发布多个主题订阅者订阅主题,发布者通知某个主题的所有订阅者更新数据。

             发布者:主题  = 1 : N, 主题:订阅者 = 1:N

             优点:降低发布者与订阅者之间的耦合性

class Dep{  //主题
    constructor(){
        this.subs=[];  //主题的订阅者列表
    }
    // 添加订阅者
    addSubs(sub){
        this.subs.push(sub);
    }
    // 通知所有该主题的订阅者进行更新
    notify(){
        this.subs.forEach((value,index)=>{
            value.update()
        });
    }
}
class Watcher{  //订阅者 观察者
    constructor(val,callback){
        this.name=val
        this.cb=callback;
    }
    update(){
        console.log(this.name+"更新了");
        this.cb();  //更新回调

    }

}

var w1=new Watcher("小明",()=>{console.log("更新成功")});
var w2=new Watcher("小红",()=>{console.log("更新成功")});
var w3=new Watcher("小李",()=>{console.log("更新成功")});
var dep=new Dep();
dep.addSubs(w1);
dep.addSubs(w2);
dep.addSubs(w3);
dep.notify();


运行结果:

小明更新了
更新成功
小红更新了
更新成功
小李更新了
更新成功

(5)观察者模式

对象之间是一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知并自动更新。

 9. 对象判等

== 与===判断的是内存地址是否相等

var obj1 = {
    name: "Benjamin",
    sex : "male"
}
var obj2 = {
    name: "Benjamin",
    sex : "male"
}

console.log(obj1 == obj2);  //false
console.log(obj1 === obj2); //false
var obj3=obj1;    
obj1==obj3  //true  
obj1===obj3 //true

10. class

// ES6 class 属于一种“语法糖”,对程序的功能并没有什么改进,只是为了方便程序员使用
function Point(x, y) {
  this.x = x;
  this.y = y;
}
 
Point.prototype.toString = function() {
  return '(' + this.x + ',' + this.y + ')';
}
等同于
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
 
  // 方法会添加到原型上
  toString() {
    return '(' + this.x + ',' + this.y + ')';
  }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值