es6学习笔记

1.promise

小知识点1:promise中的错误捕获
异步捕获不到,同步的也要一层层传递,换成async就可以在await外面套一个try来捕获了
小知识点2:Promise.resolve(x) 可以看作是 new Promise(resolve => resolve(x)) 的简写

async的返回值是一个promise。

await会将promise转为该有的内容,在await拿到之前,阻塞后面的代码。

await的好处是,对于多个异步请求进行阻塞实现某种意义上的同步,而且减少嵌套(尤其请求结果会作为中间值,是下一个请求的参数的情况),美化代码。

定义:是异步编程的一种解决方案。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

状态的特点
Promise 异步操作有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。它将执行代码与处理结果分离。

then 方法

  • then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是catch的参数,是 Promise 执行失败时的回调,两个函数只会有一个被调用。

then 方法的特点

在 JavaScript 事件队列的当前运行完成之前,回调函数永远不会被调用。

最简单的promise实例↓

 function test(resolve, reject) {//resolve与reject是默认写法
	    var timeOut = Math.random() * 2;
	    //log('set timeout to: ' + timeOut + ' seconds.');
	    setTimeout(function () {
	        if (timeOut < 1) {
	            //log('call resolve()...');
	            resolve('200 OK');
	        }
	        else {
	            //log('call reject()...');
	            reject('timeout in ' + timeOut + ' seconds.');
	        }
	    }, timeOut * 1000);
	}
	new Promise(test).then(function (result) {
	    console.log('成功:' + result);
	}).catch(function (reason) {
	    console.log('失败:' + reason);
	});

自实现promise
then中先把回调添加到队列中,当resolve开始执行时也会去执行回调

// myPromise2.0
// 实现了普通类型和MyPromise类型的链式调用
// 但是Mypromise类型异步调用then还是很难实现
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'

function MyPromise(fn) {
	const that = this
	that.state = PENDING
	that.value = null
	that.resolvedCallbacks = []
	that.rejectedCallbacks = []
	this.resolveData = null; // resolve的抛出值
	this.rejectData = null; // reject的抛出值 

	function resolve(value) {
		if (that.state === PENDING) {
			that.state = RESOLVED
			that.value = value
			that.resolvedCallbacks.map(cb => {
				that.value = cb(that.value)
				//console.log(that.value instanceof MyPromise)
				if(that.value instanceof MyPromise) {
					that.value = that.value.value;
				}
				return that.value
			})
		}
	}

	function reject(value) {
		if (that.state === PENDING) {
			that.state = REJECTED
			that.value = value;
			that.rejectedCallbacks.map(cb => cb(that.value));
		}
	}
	try {
		fn(resolve, reject)
	} catch (e) {
		reject(e)
	}
}

MyPromise.prototype.then = function(onFulfilled, onRejected) {
	const that = this
	//对传入的两个参数做判断,如果不是函数将其转为函数
	onFulfilled =
		typeof onFulfilled === 'function' ?
		onFulfilled :
		v => v // onFulfilled = v => v
	onRejected =
		typeof onRejected === 'function' ?
		onRejected :
		r => {
			throw r
		}

	if (that.state === PENDING) {
		that.resolvedCallbacks.push(onFulfilled)
		that.rejectedCallbacks.push(onRejected)
	} else if (that.state === RESOLVED) {
		onFulfilled(that.value)
	} else {
		onRejected(that.value)
	}
	return this;
}

promise.all并行限制自实现

function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
	// 已经完成个数,只有finished == array.length才能resolve
	let finished = 0;
    const ret = [];
	poolLimit = Math.min(poolLimit, array.length);
	
	function fn(index , resolve) {
		console.log(i)
		// 前i个已经在队列中,也就是说下一个要添加入队列的index
		i ++;
		
		iteratorFn(array[index]).then(function(data){
			finished ++;
			
			ret.push(data);
			if(i < array.length){
				fn(i, resolve);
			}
			else if(finished == array.length){
				resolve(ret);
			}
		})
	}
	
    return new Promise(function(resolve, reject) {
		for(let j = 0;j < poolLimit;j ++){
			fn(j, resolve);
		}
	})
}

const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i));
asyncPool(2, [1000, 5000, 3000, 2000], timeout).then(results => {
    console.log(results)
});

2.数组里面有哪些遍历方法?es6

参考https://www.cnblogs.com/sunjuncoder/p/9895438.html

  • for(){} 遍历
  • forEach 遍历,forEach不能修改数组的值
  • for-in 遍历
  • for-of 遍历
  • every()、some()、filter()、map()

3.es6新语法:let与const

var:一旦声明在当前函数中就可随意调用。
let命令:
代码块内有效;
es6之前是没有块级作用域概念的,只能用function双()来创建块级作用域,es6之后就有块级作用域了,所以产生了let变量
不能重复声明;
暂时性死区;
无变量提升;

const命令:
声明一个只读的常量,一旦声明,常量的值就不能改变;

  • let是更完美的var,不是全局变量,具有块级函数作用域,大多数情况不会发生变量提升。
  • const定义常量值,不能够重新赋值,如果值是一个对象,可以改变对象里边的属性值。
 varlet的区别:
	 var 是在全局范围内有效、let代码块内有效
	 var 可以声明多次、 let只能声明一次;
	 let 不存在变量提升,var 会变量提升;

示例:

console.log(a);  //ReferenceError: a is not defined
let a = "apple";
 
console.log(b);  //undefined
var b = "banana";
变量 b 用 var 声明存在变量提升,所以当脚本开始运行的时候,b 已经存在了,但是还没有赋值,所以会输出 undefined。
变量 a 用 let 声明不存在变量提升,在声明变量 a 之前,a 不存在,所以会报错。

const 命令
暂时性死区:

var PI = "a";
if(true){
  console.log(PI);  // ReferenceError: PI is not defined
  const PI = "3.1415926";
}

ES6 明确规定,代码块内如果存在 let 或者 const,代码块会对这些命令声明的变量从块的开始就形成一个封闭作用域。代码块内,在声明变量 PI 之前使用它会报错。

4.解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
1.对象结构赋值

let { name } = obj; //创建了一个变量name,值=obj.name

2.函数参数结构赋值

function f1({ age,height }){
        console.log(age);
        console.log(height)
    }

5.rest函数

用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

function q(...args){
       //验证args是不是数组?
       console.log(args instanceof Array);//true
       console.log(Object.prototype.toString.call(args));//"[object Array]"
       console.log(Array.isArray(args));   //true es5中的新方法
       console.log(args);
   }
   q(1,3,5);
   q(2,3,4,5,6,7,8);

6.generator

形式:

function* fib(max) {//function后面跟个*
    var
        t,
        a = 0,
        b = 1,
        n = 0;
    while (n < max) {
        yield a;//每次遇到yield,返回一个对象{value: x, done: true/false}
        [a, b] = [b, a + b];
        n ++;
    } 
    //如果遇到return,就返回done:true
    return;
    //用处,让一个函数能返回多次,每次执行需要用fib.next()
}

7.apply、call、bind

call、apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向。call后面参数用逗号隔开,apply传数组,他们作为调用函数的参数。
bind返回的是一个新函数,你必须要调用才能执行,其他和call一样。(也就是说要多加一对括号)。

8.Async/Await和Promise的区别

async的实现:
是promise和generator的语法糖,每次await的内容相当于用yield来接受,如果接受到的value为promise,则等待promise完成才继续调用next函数进行下一次yield。
介绍:

  • Async/Await是一种新的编写异步代码的方式。其他方式是回调或者Promise。
  • Async/Await实质是构建在Promise和generator之上,它不能用于纯的回调或者Node.js的回调中。
  • 和Promise一样,Async/Await是非阻塞的
  • Async/Await很大的特点是,它可以让异步代码看起来就像同步代码那样,大大提高了异步代码的可读性。

主体函数之前使用了async关键字。在函数体内,使用了await关键字。当然await关键字只能出现在用async声明的函数体内。

async/await与promise对结果处理写法不太一样,一个使用then函数,以两个返回值作为参数,一个是用await写在promise前面,如果返回1就正常执行,如果返回0就不执行并且抛出异常。

async function add1(x){
	let a=1;
	return x+a;//该函数返回值不是x+a,而是一个promise,里面带着一个resolve,带着一个11
}
console.log(add1(10));

区别:
1.简约,不需要写then。
2.错误处理,promise方法如果promise本身出错就难以处理then方法中的error,除非再写一个catch。而用async/await就能捕获到。
3.条件判别,如果要用promise拉取数据并且根据这个数据判断要不要再拉取会产生很多嵌套,而用async/await的话简洁明了,嵌套少
4.中间值,如果需要先用一个或多个promise作中间值,最后在用这些promise作参数调用其他promise的话,代码可读性会很差,因为有很多嵌套,而async/await依然不用嵌套。

9.代理模式proxy

当用户不方便访问一个对象或者不满足需求时,用代理模式创建一个替代对象实现对源对象的访问,并且在代理对象上添加拦截行为。
优点:

  • 拦截和监视外部对对象的访问
  • 降低函数或类的复杂度
  • 在复杂操作前对操作进行校验或对所需资源进行管理

proxy也可以解决跨域,搭建中间层,传输时中间层将域名转化为对方的域名,规避跨域问题。

10.generator自执行函数

function *gen(){
	let a = yield 'a';
	console.log(a);
	let b = yield 'b';
	console.log(b);
	let c = yield 'c';
	console.log(c);
}
function co(gen){
	return new Promise((resolve,reject)=>{
		let g = gen();
		function next(lastValue){
			let {value,done} = g.next(lastValue)
			if(done){
				resolve(lastValue);
			}else{
				next(value);
			}
		}
		next();
	})
}
co(gen).then((data)=>{
	console.log(data);
},(reason)=>{
	console.log(reason);
})

11.固定数量的promise并行

var p1 = function(){
	return new Promise(function(resolve,reject){
	setTimeout(function(){
		console.log('i am p1');
		resolve('11')
	},1000)
})}
var p2 = function(){
	return new Promise(function(resolve,reject){
	setTimeout(function(){
		console.log('i am p2');
		resolve('22')
	},1100)
})}
var p3 = function(){
	return new Promise(function(resolve,reject){
	setTimeout(function(){
		console.log('i am p3');
		resolve('33')
	},1000)
})}
var p4 = function(){
	return new Promise(function(resolve,reject){
	setTimeout(function(){
		console.log('i am p4');
		resolve('44')
	},1200)
})}
var p5 = function(){
	return new Promise(function(resolve,reject){
	setTimeout(function(){
		console.log('i am p5');
		resolve('55')
	},1300)
})}
function fun(arr,n){
	/* arr = arr.slice(0,n);
	
	console.time()
	Promise.all(arr.map((item)=>item())).then(function(...rest){
		console.log(...rest);
		console.timeEnd()
	}) */
	n = Math.min(arr.length,n);
	var j = n;
	for(var i = 0;i < n;i ++){
		arr[i] = arr[i]().then(handler);
	} 
	
	function handler(data){ 
		console.log(data);
		if(j < arr.length){
			arr[j] = arr[j]().then(handler);
			j ++;
		}else{
			return;
		}
	}
	//var que = [];
	//arr[0].then(()=>console.log('xx'))
}

fun([p1,p2,p3,p4,p5],2);

12.Object.defineProperty和proxy

Object.defineProperty
为什么他不能监听数组?

因为数组的length的configurable为false也不允许被改为true,描述符不能被改变导致数组length不能被监听到。
在这里插入图片描述

//参数1 目标对象
//参数2 key
//参数3 配置
//write 是否能直接赋值修改值
//enumerble 是否能枚举
//configurable 是否能删除和可配置,除value和writable特性外的其他特性是否可以被修改

let Person = {}
Object.defineProperty(Person, 'name', {
   value: 'jack',
   writable: true // 是否可以改变
})

proxy原理
proxy是对目标的一个拦截,拦截操作是在原型上,所以可以用Object.create进行继承,返回一个代理对象。

//常用handler操作
//1. get(target, propKey, receiver)
//2. set(target, propKey, value, receiver)
//3. has(target, propKey)
//4. construct(target, args):
//5. apply(target, object, args)
var target = {
	name: 'poetries'
};
var logHandler = {
	get: function(target, key) {
		console.log(`${key} 被读取`);
		return target[key];
	},
	set: function(target, key, value) {
		console.log(`${key} 被设置为 ${value}`);
		target[key] = value;
	}
}
var targetWithLog = new Proxy(target, logHandler);

14.catch实现、all实现

Promise.prototype.myCatch = function (onRejected) {
  return this.then(undefined, onRejected);
};

Promise.myAll = async function(...rest){
			var n = rest.length;
			var ans = new Array(n);
			for(let i = 0;i < rest.length;i ++){
				let p = await rest[i]
				console.log(p)
				n --;
				ans[i] = p;
			}
			return new Promise((resolve)=>{
				console.log(ans);
				resolve(ans);
			})
		}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值