ES6学习记录

1.let 和 const / Set 和 Map / int 和 string转化


1.1 let
1)声明的变量仅在块级作用域内有效
2)无变量提升,要在声明后使用
3)暂时性死区,只要块级作用域内存在let命令,它所声明的变量就绑定这个区域,不再受外部的影响
4)不允许在相同作用域内重复声明同一变量
1.2 const
1)同let
2)对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址

	const a = [];
	a.push('Hello'); // 可执行
	a.length = 0;    // 可执行
	a = ['Dave'];    // 报错

1.3 Set WeakSet 和 Map
1.3.1Set
类似于数组,但是成员的值都是唯一的,没有重复的值
操作方法:add() / delete() / has() / clear()
遍历方法:keys() / values() / entries() / forEach() (Set 的 keys 和 values 方法相同)
1)数组转set

	var arr = ["1","2","1","2","3","1"];
 	var set = new Set(arr);
 	//得到一个新的Set:{"1","2","3"};

2)set转数组

 	var arr1= Array.from(set);
 	//得到一个新的数组:["1","2","3"];

3)数组去重

	//法一
 	var arr1 = Array.from(new Set(arr));
 	//得到一个新的数组:["1","2","3"];
 	
 	//法二
 	[...new Set(arr)]

4)使用Set实现并集 / 交集 / 差集

    let a = new Set([1,2,3])
    let b = new Set([4,3,2])
    //并集
    let union = new Set([...a,...b])
    //交集
    let intersect = new Set([...a].filter(x => b.has(x)))
    //差集
    let difference = new Set([...a].filter(x => !b.has(x)))

1.3.2 WeakSet
1)特点:成员只能是对象;弱引用
2)实例:保证了Foo的实例方法,只能在Foo的实例上调用
3)分析:Foo 类中想验证 this 对象的来源,于是需要一个集合来存所有通过构造函数构建的对象,Foo类却并不像参与到实例对象的生命周期中去,直接用 Set 的话,由于Set 对于实例对象存在引用,就会发生内存泄漏。(内存泄漏:没有正确释放内存;内存溢出:申请不到足够的内存)

	const foos = new WeakSet()
	class Foo {
  		constructor() {
    		foos.add(this)
  		}
  		method () {
    		if (!foos.has(this)) {
      		throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!');
    		}
  		}
	}

1.3.3Map:键值对 {xx => xxx,xx =>xxx}
1.操作方法:size() / set(key,value) / get(key) / has(key) / delete(key) / clear()
2.遍历方法:keys() / values() / entries() / forEach()

	var m = new Map(); // 空Map
	m.set('Adam', 67); // 添加新的key-value
	m.has('Adam'); // 是否存在key 'Adam': true
	m.get('Adam'); // 67
	m.delete('Adam'); // 删除key 'Adam'

	for(let index of map.keys()){}
	for(let item of map.values()){}
	for(let [index, item] of map.entries()){}

3.与其他数据结构的交换
1)Map转为数组

    [...myMap]

2)数组转为Map

	new Map([[true, 7], [{foo: 3}, ['abc']]])

3)Map转为对象(所有Map的键都是字符串)

	function strMapToObj(strMap){
    	let obj = Object.create(null) //创建空对象
        for(let [k,v] of strMap){
        	obj[k] = v
        }
        return obj
    }
    let myMap = new Map().set('yes',true).set('no',false)
    console.log(strMapToObj(myMap))

4)对象转为Map

	function objToStrMap(obj){
    	let strMap = new Map()
    	for(let k of Object.keys(obj)){
    		strMap.set(k,obj[k])
    	}
    	return strMap
    }
    console.log(objToStrMap({yes:true,no:false}))

5)Map转为JSON

	//Map键名都是字符串,转为对象JSON
    function strMapToJson(strMap){
    	return JSON.stringify(strMapToObj(strMap))
    }
    let myMap = new Map().set('yes',true).set('no',false)
    strMapToJson(myMap) //'{'yes':true,'no':false}'
    
    //Map键名有非字符串,转为数组JSON
    function mapToArrayJson(map){
    	return JSON.stringify([...map])
    }
    let myMap = new Map().set(true,7).set({foo:3},['abc'])
    mapToArrayJson(myMap) //'[[true,7],[{'foo':3},['abc']]]'

6)JSON转为Map

 	//所有键名都是字符串
    function jsonToStrMap(jsonStr){
    	return objToStrMap(JSON.parse(jsonStr))
    }
    jsonToStrMap('{"yes":true,"no":false}') //Map {'yes' => true,'no' => false}
    
    //整个JSON就是一个数组,且每个数组成员本身,又是一个有两个成员的数组
    function jsonToMap(jsonStr){
    	return new Map(JSON.parse(jsonStr))
    }
    jsonToMap('[[true,7],[{"foo":3},["abc"]]]') //Map {true => 7,Object {foo:3} => ['abc']}

1.4 int 和 string转化
1)int 转 string
法一:x.toString()
法二:x

2 json字符串 和 json对象转化 / 解构赋值 / 模板字符串


2.1json字符串和json对象转化
1)JSON字符串 转为 JSON对象
JSON.parse(str);
2)JSON对象 转为 JSON字符
JSON.stringify(obj);
2.2解构赋值
2.2.1已声明的变量解构赋值

	// 错误的写法
	var x;
	{x} = {x: 1};//将大括号写在行首,会将{x}解释为代码块

	// 正确的写法
	({x} = {x: 1});

2.2.2将现有对象的方法赋值到某个变量

	let { log, sin, cos } = Math;

2.2.3对数组进行对象属性的解构

	var arr = [1, 2, 3];
	var {0 : first, [arr.length - 1] : last} = arr;
	first // 0键 1
	last // 2键 3

2.3模板字符串
用`(反引号)标识,用${}将变量括起来
不需使用大量的“”(双引号)和 + 来拼接

	//原js模板字符串
	$("#result").append(
        "He is <b>"+person.name+"</b>"+"and we wish to know his"+person.age+".That is all" 
        );
    //ES6模板字符串
	$("#result").append(
        `He is <b>${person.name}</b>and we wish to know his${person.age}.that is all`
    );
    //ES6调用函数
    function string(){ return "zzw likes es6!";}
	console.log(`你想说什么?
            嗯,${string()}`);

	//模板字符串被嵌套
	//标签模板,可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串
	const tmpl = addrs =>`
    	<table>
            ${addrs.map(addr =>`
                <tr><td>${addr.first}</td></tr>
                <tr><td>${addr.last}</td></tr>
            `).join("")}
        </table>
     `;
     const data = [
     	{first:'Jane',last:'Bond'},
        {first:'Lars',last:'Croft'}
     ];
     console.log(tmpl(data))

	//引入模板字符串本身
    let str = 'return' + '`Hello ${name}`'
    let func = new Function('name',str)//参数,函数体,所有的参数都为字符串形式
    func('Jack')

3 RegExp


3.1 RegExp
1)直接给出字符,就是精确匹配。用\d可以匹配一个数字,\w可以匹配一个字母或数字
2).可以匹配任意字符
3)匹配变长的字符,用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符:
例:[0-9a-zA-Z_]可以匹配一个数字、字母或者下划线,后面加一个 + 匹配至少一个
4)A|B可以匹配A或B,所以(J|j)ava(S|s)cript可以匹配四种
5)^表示行的开头,
^\d表示必须以数字开头;
KaTeX parse error: Undefined control sequence: \d at position 8: 表示行的结束,\̲d̲表示必须以数字结束。
3.2创建正则表达式
第一种方式是直接通过/正则表达式/写出来,第二种方式是通过new RegExp(‘正则表达式’)创建一个RegExp对象

	var re1 = /ABC\-001/;
	var re2 = new RegExp('ABC\\-001');

	var re = /^\d{3}\-\d{3,8}$/;
	re.test('010-12345'); // 测试是否匹配用 test()

3.3分组
()表示的就是要提取的分组,如果正则表达式中定义了组,就可以在RegExp对象上用exec()方法提取出子串来
exec()方法在匹配成功后,会返回一个Array,第一个元素是正则表达式匹配到的整个字符串,后面的字符串表示匹配成功的子串。

	var re = /^(\d+?)(0*)$/ //加个问号变为非贪婪匹配
    re.exec('102300') ['102300', '1023', '00']

3.4特殊标志
1)g 全局匹配

	var r1 = /test/g;
	// 等价于:
	var r2 = new RegExp('test', 'g');
2) i 忽略大小写
3)m 多行匹配
	var str="This is an\n antzone good"; 
	var reg=/an$/m; //如果没有加m,不能够匹配字符串"an",尽管"an"后面已经换行了,但是并没有采用多行匹配,所以不是字符串行的结尾,开头同理
	console.log(str.match(reg));

4 数值 【Number / Math】/ 数组【Array.from / Array of / find / fill / 】


4.1数值
4.1.1 Number
1)2)ES5没有 Number,是将非数值的值转为数值,再进行判断;例如“10”转化为10
ES6增加 Number ,只对数值有效
3)4)转化可为字符串如“10.1”
1)Number.isFinite : 是否有限
2)Number.isNaN :是否为非数字
3)Number.parseInt
4)Number.parseFloat
5)Number.isInteger
4.1.2 Math
1)Math.trunc : 去除一个数的小数部分,返回整数部分
2)Math.sign :判断一个数到底是正数、负数、还是零
3)Math.cbrt :计算立方根
4.2数组
4.2.1 Array.from
可将两类对象转为真正的数组:类似数组的对象 和可遍历 的对象(包括Set和Map)
1)类似数组的对象(1它必须是一个对象,键名为数值 2有length属性)

	let arrayLike = {
    	'0': 'a',
   		'1': 'b',
    	'2': 'c',
    	length: 3
	};
	let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
2)可以接收第二个参数,类似数组的map
	Array.from(arrayLike, x => x * x);
	// 等同于
	Array.from(arrayLike).map(x => x * x);

4.3.3 Array.of
用于将一组值转化为数组

	//与Array的不同
	Array.of(3) // [3]
	Array(3) // [, , ,]

4.3.4 find 和 findIndex
参数:当前的值、当前的位置和原数组
1) find:第一个返回值为true的成员,然后返回该成员
2)findIndex:返回第一个符合条件的数组成员的位置

	[1, 4, -5, 10].find((n) => n < 0) // -5
	[1, 5, 10, 15].find(function(value, index, arr) {
  		return value > 9;
	}) // 10

4.3.5 fill
参数:填充值,起始位置,结束位置(之前)

	new Array(3).fill(7) // [7, 7, 7]
	['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7, 'c']

5数组遍历【forEach / map / for of】/对象遍历【for in】


5.1 JS数组遍历
1)普通for循环
2)优化for循环:避免重复获取长度
3)forEach:不能使用break语句中断循环,也不能使用return语句返回到外层函数
4)map:同forEach,支持return返回值
5)for of:正确响应break、continue和return语句
ES6新方法:entries(),keys() 和 values(),entries()是对键值对的遍历

	//优化for
	for(var j = 0,len = arr.length; j < len; j++){ console.log(arr[j]); }
	
	//forEach
	arr.forEach(function(value,i){ console.log('forEach遍历:'+i+'--'+value); })
	
	//map
	var temp=arr.map(function(val,index){ 
		console.log(val);  
  		return val*val           
	})
	
	//for of
	for( let value of arr){ console.log(value); }
	//entries() / keys() / values()
	for (let index of ['a', 'b'].keys()) { console.log(index);} // 0 1
	for (let elem of ['a', 'b'].values()) { console.log(elem); } // 'a' 'b'
	for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem); } // 0 "a"  1 "b"

5.2 JS 对象遍历
1)for in
for in遍历的是数组或对象的索引(即键名),而for of遍历的是数组元素值

	//for in
	for (var index in arr){ console.log(arr[index]);

6 函数参数 和 解构赋值 / rest / 扩展运算符 / 箭头函数


6.1函数参数 和 解构赋值 默认值
区别:写法一函数参数的默认值是空对象,但是设置了对象解构赋值的默认值;
写法二函数参数的默认值是一个有具体属性的对象,但是没有设置对象解构赋值的默认值

	// 写法一
	function m1({x = 0, y = 0} = {}) { return [x, y];}

	// 写法二
	function m2({x, y} = { x: 0, y: 0 }) { return [x, y]; }

	// x有值,y无值的情况
	m1({x: 3}) // [3, 0]
	m2({x: 3}) // [3, undefined]

6.2 rest
形式:…变量名,搭配的变量是一个数组

	function push(array, ...items) { //注意:rest参数只能是最后一个参数
  		items.forEach(function(item) {
    		array.push(item);
    		console.log(item);
  		});
	}
	var a = [];
	push(a, 1, 2, 3)

6.3扩展运算符
形式:… 相当于rest参数的逆运算,将一个数组转为用逗号分隔的参数序列
1)注意:数组赋值只能放在参数的最后一位

	function add(x, y) { return x + y; }
	var numbers = [4, 38];
	add(...numbers) // 将数组转为函数的参数
2)任何Iterator接口的对象,都可以用扩展运算符转为真正的数组
	//例一:
	var nodeList = document.querySelectorAll('div');//返回类似数组的对象,但没有部署Iterator接口无法转化
	var array = [...nodeList];
	
	//例二
	//Map 和 Set
	let map = new Map([ [1, 'one'], [2, 'two'], [3, 'three'] ]);
	let arr = [...map.keys()]; // [1, 2, 3]

6.4箭头函数
1)定义:this对象是定义时所在的对象

	var f = v => v;
	//等同于
	var f = function(v) { return v; };

例:

	var handler = {
  		id: '123456',
  		init: function() {
    		document.addEventListener('click',
      		event => this.doSomething(event.type), false); //this指向handler对象,否则指向document对象
  		},
  		doSomething: function(type) { console.log('Handling ' + type  + ' for ' + this.id); }
	};
2)嵌套的箭头函数
	let insert = (value) => ({into: (array) => ({after: (afterValue) => { //加(),可能原因被解析成代码块
  		array.splice(array.indexOf(afterValue) + 1, 0, value);
  		return array;
	}})});
	insert(2).into([1, 3]).after(1); //[1, 2, 3]

7 简洁表示 /对象/Map转数组/ Object.assign /浅拷贝和深拷贝


7.1简洁表示
1)属性

	var foo = 'bar'
    var baz = {foo} //{foo:'bar'}
    //等同于
    var baz = {foo:foo} //属性名为变量名,属性值为变量的值
2)方法
	var o = {
  		method() { return "Hello!"; }
	};
	// 等同于
	var o = {
  		method: function() { return "Hello!";}
	};

	//适用于CommonJS模块输出变量
	module.exports = {getItem, setItem}
3)属性名表达式
注意:属性名表达式 与 简洁表示法 不能同时使用
	//表达式作为对象的属性名
	var lastWord = 'last word';
	var a = {
  		'first word': 'hello',
  		[lastWord]: 'world'
	};
	a['first word'] // "hello"
	a[lastWord] // "world"

	//作为方法名
	let obj = {
  		['h' + 'ello']() { return 'hi';}
	};
	obj.hello() // hi

7.2对象 / Map 转数组
7.2.1对象转数组
1)Array.from(object)
要求:1.object中必须有length属性,返回的数组长度取决于length长度
2.key 值必须是数值
2)Object.values(object)
3)Object.keys(object)
4)Object.entries(object)

	const obj = { foo: 'bar', baz: 42 }; 
	console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
5)push
  	let keys = []
  	for(let property in object)
    	keys.push(property)
	}

7.2.2Map转数组
快捷方式:扩展运算符(注意与 对象转数组 用法区别)

	let map = new Map([
  		[1, 'one'],
  		[2, 'two'],
  		[3, 'three'],
	]);
	[...map.keys()] // [1, 2, 3]
	[...map.values()] // ['one', 'two', 'three']
	[...map.entries()] // [[1,'one'], [2, 'two'], [3, 'three']]
	[...map] // [[1,'one'], [2, 'two'], [3, 'three']]

7.3 Object.assign
定义:用于对象的合并,第一个参数是目标对象,后面的参数都是源对象

	//例一
	var target = { a: 1 };
	var source1 = { b: 2 };
	var source2 = { c: 3 };
	Object.assign(target, source1, source2); //如果同名属性则覆盖
	target // {a:1, b:2, c:3}

	//例二
	var v1 = 'abc';
	var v2 = true;
	var v3 = 10;
	var obj = Object.assign({}, v1, v2, v3);//只有字符串的包装对象会产生可枚举的属性
	console.log(obj); // { "0": "a", "1": "b", "2": "c" }

注意:Object.assign是浅拷贝,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用

	var obj1 = {a: {b: 1}};//如果不是对象则不影响
	var obj2 = Object.assign({}, obj1);
	obj1.a.b = 2;
	obj2.a.b // 2

7.4浅拷贝和深拷贝
1)浅拷贝
对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没有开辟新的栈,修改其中一个对象的属性,则另一个对象的属性也会改变;
2)深拷贝
开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
将 浅拷贝 变为 深拷贝 方法:
1.通过JSON解析

	var test ={
	  age :40,
	 }
	  var result = JSON.parse(JSON.stringify(test))
	  //如果直接 result = test,则result改变值后test也会改变,值相等
	  result.age = 30
2.扩展运算符

注意:用扩展运算符对数组或者对象进行拷贝时,同 Object.assign ,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用

	let arr = [1, 2, 3, 4, 5, 6];
    let arr1 = [...arr];
    arr1.push(7);
    console.log(arr); //[1, 2, 3, 4, 5, 6]
    console.log(arr1); //[1, 2, 3, 4, 5, 6, 7]
3.Object.assign
	let aClone = Object.assign({}, a);

8 Symbol / Proxy / Iterator /类似数组的对象 / Generator


8.1 Symbol
特点:每一个Symbol值都不等
1)作为属性名

	//不能用.运算符,否则会被当做字符串而不是Symbol值
	var mySymbol = Symbol();
	var a = {
  		[mySymbol]: 'Hello!'
	};
	a[mySymbol] //'Hello!'

	//对象中同理,必须放入[]中
	let s = Symbol();
	let obj = {
  		[s]: function (arg) { ... }
	};
	obj[s](123);

2)Symbol.for
定义:搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值

	var s1 = Symbol.for('foo');//与Symbol不同是Symbol.for会被登记在全局环境中供搜索
	var s2 = Symbol.for('foo');
	s1 === s2 // true

3)Symbol.keyfor
定义:返回一个已登记的 Symbol 类型值的key

	var s1 = Symbol.for('foo')
	Symbol.keyfor(s1) //'foo'

4)用途之一
避免实例自定义的属性或方法覆盖原型上的属性或方法

	function Foo(name){ this.name = name }
    Foo.prototype.say = function(){ return this.name }
    var f = new Foo('f')
    var say = Symbol('say')
    f[say] = function(){ return 'other name' }
    f.say() //'f'
    f[say]() //'other name'

8.2 Proxy 代理
定义:在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截
1)get:用于拦截属性的读取操作

	var person = {
    	name:'张三'
    }
    var proxy = new Proxy(person,{
    	get:function(target, property){
        	if(property in target){
            	return target[property]
            }else{
            	throw new ReferenceError("不存在")
            }
         }
     })
     proxy.name //'张三'
     proxy.age //错误

2)set:用于拦截属性的赋值操作

	let validator = {
    	set:function(obj, prop, value){
        	if(prop === 'age'){
            	if(!Number.isInteger(value)){
                	throw new TypeError('The age is not an integer')
                }
            }
        	obj[prop] = value
        }
    }
    let person = new Proxy({},validator)
    person.age = 100
    person.age //100
    person.age = 'young' //报错

8.3 Iterator 迭代器
定义:只要部署了 Iterator 接口,具有Symbol.iterator属性,就是可遍历的
有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set和Map结构

	const banji = {
    	name:"终极一班",
        stus:[
        	'xiaoming',
            'knight'
        ],
        [Symbol.iterator](){ //直接无法遍历,要加迭代器
        	let index = 0;
            let _this = this
            return{
            	next:function(){ //next方法
                	if(index<_this.stus.length){
                    	const result = {value:_this.stus[index], done:false} //直接使用this指向next方法
                        index++
                        return result
                    }else{
                        return {value:undefined, done:true}
                    }
                }
            }
        }
    }
    for(let n of banji){ console.log(n) } //xiaoming knight

8.4类似数组的对象
1)字符串
2)DOM NodeList对象

	let paras = document.querySelectorAll('p')
    for(let p of paras){
    	p.classList.add("test") //classList得到类名,并添加test类名
    }

3)arguments对象
定义:每个函数都会有一个Arguments对象实例arguments,引用函数的实参,可以用数组下标的方式"[]"引用arguments的元素

	function printArgs() {
  		for (let x of arguments) {
    		console.log(x); //'a' 'b'
  		}
	}
	printArgs('a', 'b');

8.5 Generator
1)总结:调用Generator函数,返回一个遍历器对象,代表Generator函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield语句后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

	function* helloWorldGenerator() {
  		yield 'hello';
  		yield 'world';
  		return 'ending';
	}
	var hw = helloWorldGenerator();
	hw.next() // { value: 'hello', done: false }
	hw.next() // { value: 'world', done: false }
	hw.next() // { value: 'ending', done: true }
	hw.next() // { value: undefined, done: true } 为true的值就是最后返回的值

2)next参数
定义:next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值

	function* foo(x) {
  		var y = 2 * (yield (x + 1));
  		var z = yield (y / 3);
  		return (x + y + z);
	}

	var a = foo(5);
	a.next() // Object{value:6, done:false}
	a.next() // Object{value:NaN, done:false}
	a.next() // Object{value:NaN, done:true}

	var b = foo(5);
	b.next() // { value:6, done:false }
	b.next(12) // { value:8, done:false }
	b.next(13) // { value:42, done:true }  x=5,y=24

3)for…of / 扩展运算符(…)/ 解构赋值 / Array.from 可以自动遍历Generator函数时生成的Iterator对象

	function *foo() {
  		yield 1;
  		yield 2;
  		return 3; //不包括return
	}
	for (let v of foo()) { console.log(v); } // 1 2
	[...foo()] //[1,2]
	Array.from(foo()) //[1,2]
	let [x,y] = foo() //x为1,y为2

4)异步实例

		function getUsers(){
            setTimeout(() => {
                let data = '用户数据'
                iterator.next(data)//调用next方法,并且将数据传入
            }, 1000);
        }
        function getOrders(){
            setTimeout(() => {
                let data = '订单数据'
                iterator.next()
            }, 1000);
        }
        function* generator(){
            let users = yield getUsers();//返回用户数据
            yield getOrders()
        }
        let iterator = generator()
        iterator.next()

9 Promise


9.1定义
优点:将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
缺点:1)无法取消Promise,一旦新建它就会立即执行,无法中途取消;2)如果不设置回调函数,Promise内部抛出的错误,不会反应到外部;3)当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

	var promise = new Promise(function(resolve, reject) {
  		if (/* 异步操作成功 */){
    		resolve(value);
  		} else {
   		reject(error);
  		}	
	});
	promise.then(function(value) {
  		// success
	}, function(error) {
  		// failure
	});
	//.catch()方法是.then(null,rejection)的别名,更推荐使用catch

9.2 Promise.all() / Promise.race() / Promise.resolve() / Promise.reject() / Promist.try()
1)Promise.all()
定义:用于将多个Promise实例,包装成一个新的Promise实例。接受一个数组作为参数,p1、p2、p3都是Promise对象的实例
p的状态:1)p1、p2、p3的状态都为fulfilled,p的状态为fulfilled;p1、p2、p3的返回值组成一个数组,传递给p的回调函数
2)p1、p2、p3有一个被rejected,p的状态就变成rejected;第一个被reject的实例的返回值,传递给p的回调函数
用途:如 当一个页面需要在很多个模块的数据都返回回来时才正常显示,否则loading

	var p = Promise.all([p1, p2, p3]);

2)Promise.race()
定义:有一个实例率先改变状态,p的状态就发生改变,率先改变的 Promise 实例的返回值,就传递给p的回调函数
用途:一般用于和定时器绑定,比如将一个请求和一个三秒的定时器包装成Promise实例,加入到race队列中,请求三秒中还没有回应时,给用户一些提示或一些相应的操作
3)Promise.resolve()
定义:将现有对象转为Promise对象

	//参数是一个thenable对象(具有then方法的对象)
	let thenable = {
  		then: function(resolve, reject) {
    		resolve(42);
  		}
	};
	let p1 = Promise.resolve(thenable);
	p1.then(function(value) {
  		console.log(value);  // 42
	});
	
	//参数不是具有then方法的对象,或根本就不是对象
	var p = Promise.resolve('Hello');
	p.then(function (s){ console.log(s) }); // Hello

4)Promise.reject() 用法同上
5)Promise.try()
定义:同步函数同步执行,异步函数异步执行

	const f = ()=> console.log('now')
    Promise.try(f)
    console.log('next')//now next

10 异步操作 和 Async函数


10.1异步
异步:一个任务分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段
例如,有一个任务是读取文件进行处理,任务的第一段是向操作系统发出请求,要求读取文件。然后,程序执行其他任务,等到操作系统返回文件,再接着执行任务的第二段(处理文件)。这种不连续的执行,就叫做异步。
同步:连续的执行就叫做同步
10.2 async函数
10.2.1定义:Generator函数的语法糖。就是将Generator函数的 * 替换成 async ,将 yield 替换成 await,使其看起来更像同步代码
一般在await后放Promise对象,async值和Promise的返回值相同(resolve),await接收结果

	//Generator函数
	var gen = function* (){
  		var f1 = yield readFile('/etc/fstab');
  		var f2 = yield readFile('/etc/shells');
	};
	//async函数
	var asyncReadFile = async function(){
    	var f1 = await readFile('/etc/fstab')
        var f2 = await readFile('/etc/shells')
    }

10.2.2 async函数
1.async函数返回一个Promise对象

	//await后放Promise对象
	function timeout(ms) {
  		return new Promise((resolve) => {
    		setTimeout(resolve, ms);
  		});
	}
	async function asyncPrint(value, ms) {
  		await timeout(ms);
  		console.log(value)
	}
	asyncPrint('hello world', 50); //50毫秒后打印出hello world

	//return语句返回的值,会成为then方法回调函数的参数
	async function f(){
    	return 'hello world'
    }
    f().then(v => console.log(v)) //hello world

	//内部抛出错误,会导致返回的Promise对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到
	async function f() {
  		throw new Error('出错了');
	}
	f().then(
  		v => console.log(v),
  		e => console.log(e)
	) // Error: 出错了

2.注意:
1)await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try…catch代码块中(因为rejected不执行下面代码)

	async function myFunction() {
  		try {
    		await somethingThatReturnsAPromise();
  		} catch (err) {
    	console.log(err);
  		}
	}

2)多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发

	//该写法只有getFoo完成以后,才会执行getBar
	let foo = await getFoo();
	let bar = await getBar();

	//法一
	let [foo, bar] = await Promise.all([getFoo(),getBar()])
	//法二
    let fooPromise = getFoo()
    let barPromise = getBar()
    let foo = await fooPromise
    let bar = await barPromise

3)await命令只能用在async函数之中,不能用在普通函数

11 Class / Module


11.1 Class(ES5使用function)
1)子类的构造方法中,只有调用super之后才能使用this关键字
2)super指向父类的原型对象,定义在父类实例上的方法或属性无法通过super调用,例如constructor中的属性
super绑定子类的this
3)静态属性
静态成员属于类(es6)/函数(es5),不属于实例,只能通过对象调用
ES6的Class内部只有静态方法,没有静态属性;ES7中类的静态属性在实例属性前加上static

    class Foo{
        static myStaticProp = 42 //ES7静态属性写法
    }
    Foo.prop = 1 //ES6中Foo类定义静态属性

11.2继承
1)ES5构造函数继承

		function Phone(brand,price){
            this.brand = brand
            this.price = price
        }
        Phone.prototype.call = function(){
            console.log("打电话")
        }
        function SmartPhone(brand,price,color,size){
            Phone.call(this,brand,price) //继承父构造函数的属性
            this.color = color
            this.size = size
        }
        //借用原型对象继承方法
        SmartPhone.prototype = new Phone()
        SmartPhone.prototype.constructor = SmartPhone
        SmartPhone.prototype.phone = function(){
            console.log("我可以拍照")
        }
        const chuizi = new SmartPhone('锤子',2499,'黑色',6.6)

2)ES6类继承(更符合面向对象)
注意:子类中普通成员方法不能使用super调父类的同名方法,只能重写

		class Phone{
            constructor(brand,price){
                this.brand = brand
                this.price = price
            }
            call(){
                console.log('我可以打电话')
            }
        }
        class SmartPhone extends Phone{
            constructor(brand,price,color,size){
                super(brand,price)//Phone.call(this,brand,price)
                this.color = color
                this.size = size
            }
            photo(){
                console.log("拍照")
            }
        }
        const xiaomi = new SmartPhone('小米',799,'黑色','6.6')

11.3 get 和 set
get 当访问该属性时调用该函数。可以应用在变化的属性,如sum值
set 当该属性被赋值时,所绑定的函数就会被调用。可以应用在判断设置值是否合法

    class Fruit {
      constructor(name='香蕉',size='10斤') {
        this.name = name
        this.size = size
      }
      get getName(){
        return this.name
      }
      set setName(value){
        this.name = value
      }
    }
    let f1 = new Fruit()
    f1.setName='柿子'

11.4 Module
export 和 export default 区别:
1)export default 对应的import语句不需要使用大括号;export 对应的import语句需要使用大括号。(因为 export default 用于指定模块的默认输出,一个模块只能有一个默认输出)
2)export,可以获取模块内部实时的值,不同脚本加载模块得到同一实例;而CommonJS不能动态更新

		//CommonJS模块
        let {stat, exists, readFile} = require('fs')//加载fs模块
        //ES6模块
        import {stat, exists, readFile} from 'fs'//加载三个方法
        
        var firstName = 'Michael'
        var lastName = 'Jackson'
        export{firstName, lastName}//输出变量

        function v1(){}
        function v2(){}
        export{
            v1 as streamV1,
            V2 as streamV2
        }//输出重命名的函数

        //import,不能使用表达式 / 变量 / if语句
        import {lastName as surname} from './profile'//as为重命名输入变量
        //整体加载,用*指定一个对象
        import * as circle from './circle'

		//合并
        //constants/index.js
        export {db} from './db'
        export {users} from './users'//import 和 export 值相同可以的写法
        //script.js
        import {db,users} from './constants'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值