let和const
- let和const有块级作用域
- 变量不能重复let定义
let a = 1;
let a = 2;//报错
- const定义时就要赋值
- const常量名称应该是全大写
- const定义的数据不能再发生更改,但是对于对象来说,只有地址不能发生更改,里面的属性是可以更改的
变量引用
es5中我们文本赋值的形式如下
document.getElementById('p1').innerHTML = "This demonstrates the output of HTML \
content to the page, including student's\
" + name + ", " + seatNumber + ", " + sex + " and so on.";
es6中可以用反引号和${}完成
document.getElementById('p2').innerHTML = `This demonstrates the output of HTML content to the page,
including student's ${name.split('').reverse().join('')}, ${parseInt(seatNumber)+1}, ${sex} and so on.`
解构赋值
- 数组结构赋值√
- 直接赋值
[a, b] = [1, 2]; - 取前n个值或后n个值的数组
[a, b, ...rest] = [1, 2, 3, 4, 5, 6, 7];
[a,,,,...b] = [1, 2, 3, 4, 5, 6, 7]; - 设置默认值
[a, b, c = 3] = [1, 2]; - 交换值
[a, b] = [b, a];
- 对象解构赋值√
- 通过key取value
const student = {
name: 'susan',
age: '22',
sex: 'male',
height: '183cm'
}
const {name, height, sex, age} = student;
let {a,b} = {a: 1, b: 2};
({a, b} = {a: 1, b: 2});
- 设置默认值
({a=10, b=13} = {a: 1, b: 2});
- 多层参数取值
let metaData = {
title:'abc',
test:[{
title: 'test',
desc:'description'
}]
}
let {title:esTitle,test:[{title:cnTitle}]} = metaData;
- 字符串解构赋值
- 布尔值解构赋值
- 函数参数解构赋值√
{
// 代码1:左边为默认值
function move({x = 0, y = 0} = {}) {
return [x, y];
}
console.log(move({x: 3, y: 8})); // [3, 8]
console.log(move({x: 3})); // [3, 0]
console.log(move({})); // [0, 0]
console.log(move()); // [0, 0]
//
// 代码2:
function move2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
console.log(move2({x: 3, y: 8})); // [3, 8]
console.log(move2({x: 3})); // [3, undefined]
console.log(move2({})); // [undefined, undefined]
console.log(move2()); // [0, 0]
}
- 数值解构赋值
正则表达式
- es5中
let regex = new RegExp('xyz','i');
let regex2 = new RegExp(/xyz/i);
console.log(regex.test('xyz123')); //true
console.log(regex2.test('xyz123')); //true
es6中可以将上两种写法杂合在一起
let regex3 = new RegExp(/xyz/ig,'i');//i会覆盖ig
console.log(regex3.flags);//i flags也是新增的,用于获取表达式范围
- y修饰符(全局查找,但是只能匹配第一个字符就找到的形式)
let s = 'bbb_bb_b';
let a1 = /b+/g;//全局 可以多次搜索 从上次找到的位置往后搜索
let a2 = /b+/y;//全局 查找的第一个字符必须匹配
console.log('one',a1.exec(s),a2.exec(s));//one ["bbb", index: 0, input: "bbb_bb_b", groups: undefined] ["bbb", index: 0, input: "bbb_bb_b", groups: undefined]
console.log('two',a1.exec(s),a2.exec(s));//two ["bb", index: 4, input: "bbb_bb_b", groups: undefined] null
console.log(a1.sticky,a2.sticky);//false true判断是否开启带y的表达式
console.log(a1.test(s));//true
console.log(a2.test(s));//false
- u修饰符(u表示Unicode 处理Unicode字符的匹配)
console.log('u-1',/^\uD83D/.test('\uD83D\uDC2A'));//true \uD83D\uDC2A四个字节被视为两个字符
console.log('u-2',/^\uD83D/u.test('\uD83D\uDC2A'));//false 加u后\uD83D\uDC2A四个字节被视为一个字符
console.log(/\u{61}/.test('a'));//false
console.log(/\u{61}/u.test('a'));//true 加上u {}内的才会被认为是unicode
console.log('\u{20BB7}');
let s = '𠮷';
console.log('u',/^.$/.test(s));//false .是任何字符,但是匹配不上
console.log('u-2',/^.$/u.test(s));//true 加上u,能匹配,字符大于两个字节时,要加上u
console.log('test',/𠮷{2}/.test('𠮷𠮷'));//false
console.log('test',/𠮷{2}/u.test('𠮷𠮷'));//true
- s修饰符
s修饰符 es6中没有实现 功能是处理换行等字符
字符串处理
- es5中只能处理两个字节的字符,当字符大于0xfff时,会被视为两个字符,从而处理失败
console.log('a','\u0061');
console.log('b','\u20bb7');//比0xfff大 所以被视为两个字符 ₻7
console.log('c','\u{20bb7}')//𠮷(可以加上{}处理)
let s = '𠮷';
console.log('length',s.length);//2
//取第n个字符
console.log('0',s.charAt(0));//0 � 乱码
console.log('1',s.charAt(1));//1 �
//取第n个字符的Unicode
console.log('u0',s.charCodeAt(0));//u0 55362
console.log('u1',s.charCodeAt(1));//u1 57271
// 总结:es5中,对Unicode的处理是不到位的
es6中提出了新的方法,可以取到完整的字符,但是codePointAt()取一个完整字符的第二个字节时,跟es5取的一样
//es6处理四个及以上字节的字符
let s = '𠮷a';
console.log('length',s.length);//3
console.log('code0',s.codePointAt(0));//134071 取到了四个字节,是第一个完整的字符
console.log('code0',s.codePointAt(0).toString(16));//20bb7
console.log('code1',s.codePointAt(1));//57271 取得还是第3,4个字节(因为一共有三个字节 如果1取的是a 2就没有取了)
console.log('code2',s.codePointAt(2));//97 取得还是第3,4个字节
let s1 = '𠮷𠮷aa𠮷a';
console.log('code0',s1.codePointAt(0));//134071
console.log('code1',s1.codePointAt(1));//57271
console.log('code2',s1.codePointAt(2));//134071
console.log('code3',s1.codePointAt(3));//57271
console.log('code4',s1.codePointAt(4));//97
console.log('code5',s1.codePointAt(5));//97
console.log('code6',s1.codePointAt(6));//134071
console.log('code7',s1.codePointAt(7));//57271
console.log('code8',s1.codePointAt(8));//97
- Unicode转字符
console.log(String.fromCharCode('0x20bb7'));//ஷ es5
console.log(String.fromCodePoint('0x20bb7'));//𠮷 es6
- 字符串遍历
let str = '\u{20bb7}abc';
//es5
for(let i = 0;i<str.length;i++){
console.log('es5',str[i]);//乱码 a b c es5
}
//es6
for(let code of str){
console.log('es6',code);//𠮷 a b c es6
}
- 判断字符串中是否包含指定字符
let str = 'string';
console.log(str.includes('r'));//true 是否包含
console.log(str.startsWith('str'));//true 是否以其开头
console.log(str.endsWith('ng'));//true 是否以其结尾
- 重复字符串指定次
let str = 'abc';
console.log(str.repeat(4));//abcabcabcabc
- 字符串拼接
let name = 'Lili';
let info = 'Hello World';
let m = `My name is ${name},I said "${info}"`;
- 字符串补齐
let str = '3';
console.log('1',str.padStart(2,'0'));//向前补(时间)
console.log('2',str.padEnd(2,'0'));//向后补
- 定义字符串拼接方法
let user = {
name:'Lili',
info:'hello world'
};
console.log(abc`My name is ${user.name},I said "${user.info}`);//My name is ,,I said ",Lilihello world
// abc`My name is ${user.name},I said "${user.info}`;
function abc(s,v1,v2) {
console.log(s,v1,v2);//["My name is ", ",I said "", "", raw: Array(3)] "list" "hello world"
console.log(s);//["My name is ", ",I said "", "", ""]
console.log(v1);//Lili
console.log(v2);//hello world
//可以处理不同情况下的返回情况
return s+v1+v2;//My name is ,,I said ",Lilihello world
}
- raw处理转义斜杠
console.log(String.raw`Hi\n${1+2}`);//Hi\n3 raw对所有的斜杠进行了转义
console.log(`Hi\n${1+2}`);//Hi(换行)3
数值处理
- 进制处理
console.log(0b1101111);//111 二进制
console.log(0o157);//111 八进制
console.log(111);//111 十进制
console.log(0x6F);//111 十六进制
- 判断数是否是有尽的
console.log('15',Number.isFinite(15));//true
console.log('NaN',Number.isFinite(NaN));//false
console.log('1/0',Number.isFinite(1/0));//false
- 判断是否是数(是数返回false)
console.log('NaN',Number.isNaN(NaN));//true
console.log('0',Number.isNaN(0));//false
- 判断是否是整数 会将小数转为整数 不会将字符串转为数值
console.log('25',Number.isInteger(25));//true
console.log('25.0',Number.isInteger(25.0));//true 自动转义 小数转整数
console.log('25.1',Number.isInteger(25.1));//false
console.log('NaN',Number.isInteger(NaN));//false
console.log('25',Number.isInteger('25'));//false 不会将字符串转为数值
- 最大值和最小值
//-2^52 2^53 范围
console.log(Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER);//9007199254740991 -9007199254740991
// 判断是否在有效范围
console.log('10',Number.isSafeInteger(10));//true
console.log('a',Number.isSafeInteger('a'));//false
- 返回浮点数的整数部分
console.log('4.1',Math.trunc(4.1));//4
console.log('4.9',Math.trunc(4.9));//4
console.log('4.1',Math.floor(4.1));//4 向下取整
console.log('4.1',Math.ceil(4.1));//5 向上取整
console.log('4.1',Math.round(4.1));//4 四舍五入
console.log('4.5',Math.round(4.5));//5 四舍五入
- 判断是正数 负数 还是0(会将可转换的字符串转为数值)
console.log('-5',Math.sign(-5));//-1
console.log('5',Math.sign(5));//1
console.log('0',Math.sign(0));//0
console.log('50',Math.sign('50'));//1
console.log('foo',Math.sign('foo'));//NaN
- 立方根
console.log('-1',Math.cbrt(-1));//-1
console.log('64',Math.cbrt(64));//4
数组处理
- 将一系列数值转为数组
let arr = Array.of(3,4,7,9,11);
console.log(arr);//[3, 4, 7, 9, 11]
let empty = Array.of();
console.log(empty);//[]
- 将伪数组或可遍历数组转为真数组
let p = document.querySelectorAll('p');
// p.push(2); 报错 因为这不是一个真正的数组
console.log(p);
//将伪数组或可遍历对象转换为真数组
let pArr = Array.from(p);
p.forEach(function (item) {
console.log(item.textContent);
})
//Array.from(需要转换的类数组对象,类似数组的map方法,绑定map中用到的this)
console.log(Array.from([1,2,4],function (item) {
return item*2;
}))//[2, 4, 8]
- 数组中的替换
console.log('fill-7',[1,'a',undefined].fill(7));//每一个元素变成7 [7, 7, 7]
console.log('fill,pos',['a','b','c'].fill(7,1,3))//["a", 7, 7] fill(替换元素,开始位置,结束位置)
//指定由数组中的某几个元素替换某几个元素
console.log([1,2,3,4,5].copyWithin(0,1,5))// [2, 3, 4, 5, 5] copyWithin(被覆盖位置开始,开始取的位置,结束取的位置)
- 数组遍历
for(let index of ['1','c','ks'].keys()){
console.log('keys',index);//0 1 2
}
for(let value of ['1','c','ks'].values()){
console.log('keys',value); //1 c ks
}
for(let [index,value] of ['1','c','ks'].entries()){
console.log('keys',index,value);//0 1 1 c 2 ks
}
- 数组查找
console.log([1,2,3,4,5,6].find(function (item) {
return item>3;//4 找到的第一个的值
}))
console.log([1,2,3,4,5,6].findIndex(function (item) {
return item>3;//3 找到的第一个的下标
}))
- 判断数组中是否包含查找的元素
console.log('number',[1,2,NaN,'a',4].includes(4));//true
console.log('number',[1,2,NaN,'a',4].includes(NaN));//true
函数处理
- 函数入参设置默认值
function test(x,y = 'world',c) {
console.log('默认值',x,y,c)
}
test('hello');// hello world undefined
test('hello','Lili','11');//hello Lili 11
- 入参默认值是变量时,如果入参内有,就取入参内的,如果入参内没有,就去外面的
let x = 'test';
function test2(x,y=x) {//y取的是同是入参的x
console.log('作用域',x,y);
}
test2('Lili');//Lili Lili
function test3(y=x) {//当入参没有x时 取的是外面的x
console.log('作用域',y);// test
}
test3();
- 当入参个数不确定时,如何获取所有入参
function test(...args) {
for(let v of args){
console.log(v);// 1 2 3 4 'a'
}
}
test(1,2,3,4,'a');
- 数组转为离散值
console.log(...[1,2,3]);//1 2 3
- 箭头函数
let arrow = v => v*2;
console.log(arrow(3));//6
let arrow2 = () => 5;
console.log(arrow2(3));//5
- 伪调用
// 使用场景: 某一个功能依赖另一个功能 或者重复嵌套
function tail(x) {
console.log('tail',x);
}
function fx(x) {
return tail(x);
}
fx(123);
对象处理
- es5和es6对象和函数的简洁表示法
let o = 1;
let k = 2;
let es5 = {
o:o,
k:k
}
// 简洁表示法
let es6 = {
o,k
}
console.log(es5,es6)//{o:1,k:2} {o:1,k:2}
let es5_method = {
hello:function () {
console.log('hello');
}
}
let es6_method = {
hello () {
console.log('hello');
}
}
es5_method.hello();//hello
es6_method.hello();//hello
let {a,b,d} = {a:'aaa',b:'bbb',c:'ccc',d:'ddd',e:'eee'};
console.log(a,b,d);//aaa bbb ddd
- 对象属性处理
let a = 'b';
let es5_obj = {
a:'c'
};
let es6_obj = {
[a]:'c'//会先进行计算
}
console.log(es5_obj,es6_obj);//{a:'c'} {b:'c'}
- 判断两个值(非对象)是否相等
console.log('字符串',Object.is('abc','abc'),'abc'==='abc');//true
console.log('数组',Object.is([1,2,3],[1,2,3]),[1,2,3]===[1,2,3]);//false
- 拷贝(浅拷贝)
// 拷贝 assign(要拷贝到的值,拷贝的值)
// 浅拷贝 1.拷贝的只是地址 2.拷贝的是本身的属性,继承的属性不拷贝,不可枚举的属性也不会拷贝
console.log('字符串',Object.assign({a:'a',b:'b'},{c:'c'}));//{a: "a", b: "b", c: "c"}
- 属性遍历
let test = {k:123,o:456};
for(let [key,value] of Object.entries(test)){
console.log(key,value)
}
symbol类型处理
symbol 用symbol定义的基本类型 是不相等的(类似对象,不管值怎么样,地址永远不同)
- symbol的使用
let a1 = Symbol();
let a2 = Symbol();
console.log(a1 == a2);//false
//定义一个key值
let a3 = Symbol.for('a3');
let a4 = Symbol.for('a3');
console.log(a3 == a4);//true
let a1 = Symbol.for('abc');
let obj = {
[a1]:'123',
'abc':345,
'c':456
}
console.log(obj);//{abc: 345, c: 456, Symbol(abc): "123"}
- 有symbol属性的遍历
//非symbol属性
for (let [key,value] of Object.entries(obj)){
console.log(key,value);//abc 345 c 456 symbol属性取不到
}
//symbol属性
Object.getOwnPropertySymbols(obj).forEach(function (key,value) {
console.log(key,value);//Symbol(abc) 0
})
//取所有的属性
Reflect.ownKeys(obj).forEach(function (key,value) {
console.log(key,value);//abc 345 c 456 Symbol(abc) 0
})
数据结构 Set weakSet Map weakMap
set 一种集合,可以视为数组,但是里面的值不能重复
weakSet
- 支持的数据类型不一样,weakSet的值必须是对象
- weakSet都是弱引用,即引用的都是地址,也不会检测这个地址是不是被垃圾回收掉了
- 有一些方法和属性weakSet中没有 没有clear方法 set属性 不能遍历
map 相当于object map的key可以是任意的数据类型 object的key必须是字符串
weakMap 接受的key值必须是对象 没有clear set方法 不能遍历
/*
* set 一种集合,可以视为数组,但是里面的值不嫩重复
* map 相当于object map的key可以是任意的数据类型 object的key必须是字符串
* */
{
let list = new Set();
list.add(5);
list.add(7);
//长度
console.log('size',list.size);//2
}
{
let arr = [1,2,3,4,5];
let list = new Set(arr);
console.log('size',list.size)//5
}
{
//添加重复的值 不生效 可以用于去重 但是不会自动转字符串和数值
let list = new Set();
list.add(1);
list.add(5);
list.add(1);
console.log('size',list.size);//2
let arr = [1,2,3,4,5,1,2];
let lists = new Set(arr);
console.log(lists);//1,2,3,4,5
let arr2 = [1,2,3,4,5,'2',2];
let lists2 = new Set(arr2);
console.log(lists2);//1,2,3,4,5,'2'
}
{
let arr = ['add','delete','clear','has'];
let list = new Set(arr);
console.log('has',list.has('add'));//true
console.log('has',list.add('add2'));//{"add", "delete", "clear", "has", "add2"}
console.log('has',list.delete('add'));//true
console.log(list);//{"delete", "clear", "has", "add2"}
console.log('has',list.clear());//undefined
console.log(list);//Set(0) {}
}
{
let arr = ['add','delete','clear','has'];
let list = new Set(arr);
//key和value都是一样的值 都是元素本身
for (let key of list.keys()){
console.log('keys',key); //add delete clear has
}
for (let value of list.values()){
console.log('values',value);//add delete clear has
}
for (let value of list){
console.log('value',value);//add delete clear has
}
list.forEach(function (item) {
console.log(item)//add delete clear has
})
}
{
let weakList = new WeakSet();
// 与set的区别:1. 支持的数据类型不一样,weakSet的值必须是对象 2. weakSet都是弱引用,即引用的都是地址,也不会检测这个地址是不是被垃圾回收掉了
// 有一些方法和属性weakSet中没有 没有clear方法 set属性 不能遍历
let arg = {};
weakList.add(arg);
// weakList.add(2); 无效值
console.log(weakList);
}
{
let map = new Map();
let arr = ['123'];
map.set(arr,456);
console.log(map,map.get(arr)); //{Array(1) => 456} 456
}
{
let map = new Map([['a',123],['b',456]]);
console.log(map,map.size);// {"a" => 123, "b" => 456} 2
console.log('delete',map.delete('a'),map);//{"b" => 456}
console.log('clear',map.clear(),map);//{}
}
{
//接受的key值必须是对象 没有clear set方法 不能遍历
let weakMap = new WeakMap();
let o = {};
weakMap.set(o,123);
console.log(weakMap.get(o)); //123
}
set map array object的区别
- set map array的区别
let map = new Map();
let set = new Set();
let array = [];
//增
map.set('t',1);
set.add({t:1});
array.push({t:123});
// 查
let map_exist = map.has('t');
let set_exist = set.has({t:1});//查地址才能查到 false
let array_exist = array.find(item=>item.t);
// 改
map.set('t',2);
set.forEach(item => item.t?item.t=2:'');
array.forEach(item => item.t?item.t=2:'');
// 删
map.delete('t');
set.forEach(item=>item.t?set.delete(item):'');
let index = array.findIndex(item=>item.t);
array.splice(index,1);
总结:当要存储对象时,set和array都不那么方便
- set map object的区别
let item = {t:1};
let map = new Map();
let set = new Set();
let obj = {};
// 增
map.set('t',1);
set.add(item);
obj['t'] = 1;
console.log('map',map);
console.log('set',set);
console.log('obj',obj);
// 查
console.log(map.has('t'));
console.log(set.has(item));
console.log('t' in obj);
// 改
map.set('t',2);
item.t = 2;
obj['t'] = 2;
console.log('map',map);
console.log('set',set);
console.log('obj',obj);
// 删
map.delete('t');
set.delete(item);
delete obj['t'];
console.log('map',map);
console.log('set',set);
console.log('obj',obj);
总结:可以放弃array和object了,能使用map的时候就使用mao,如果对存储的数据有唯一性要求,就用set
proxy和reflect
- proxy即代理,代理了对象,不能直接操作对象,可以用于拦截增删查改等操作
let obj = {
time:'2017-01-01',
name:'Lili',
_r:123
};
//代理 不能直接操作
let monitor = new Proxy(obj,{
//拦截对象属性的读取
get(target,key){
return target[key].replace('2017','2018');
},
// 拦截对象设置属性
set(target,key,value){
if(key === 'name'){
return target[key] = value;
}
else{
return target[key];
}
},
// 判断当前对象中是否有指定属性
has(target,key){
if(key === 'name'){
return target[key];
}
else{
return false;
}
},
//拦截delete
deleteProperty(target,key){
if(key.substr(0,1) == '_'){
delete target[key];
return true;
}
else{
return target[key];
}
},
//拦截 Object.keys Object.getOwnPropertySymbols() Object.getOwnPropertyNames()
ownKeys(target){
return Object.keys(target).filter(item=>item!='time')
}
})
console.log('time',monitor.time);
monitor.time = '2111';
monitor.name = 'Tina';
console.log('set',monitor);
console.log('has','name' in monitor,'time' in monitor);
delete monitor.time;
delete monitor._r;
console.log('delete',monitor);
console.log('ownKeys',Object.keys(monitor));//name
- reflect 反射
可以理解为 reflect是一个全局对象,他上面挂载了对象的某些特殊方法,这些方法可以通过Reflect.apply这种形式来使用,当然所有方法都是可以在 Object 的原型链中找到的.
① 输入校验
function vaildator(target,vaildator) {
return new Proxy(target,{
_vaildator:vaildator,
set(target,key,value,proxy){
if(target.hasOwnProperty(key)){
let va = this._vaildator[key];
if (!!va(value)){
return Reflect.set(target,key,value,proxy)
}
else{
throw Error(`不能设置${key}到${value}`)
}
}
else{
throw Error(`${key} 不存在`)
}
}
})
}
const personVaildators = {
name(val){
if(typeof val != 'string'){
return false;
}
},
age(val){
if(typeof val != 'number' || val <= 18){
return false;
}
}
}
class Person{
constructor(name,age){
this.name = name;
this.age = age;
return vaildator(this,personVaildators)
}
}
const person = new Person('Lilei',30);
console.log(person);
person.age = 12;
②对象多重继承
var obj1 = {
name: "obj-1",
foo() {
console.log( "obj1.foo:", this.name );
}
},
obj2 = {
name: "obj-2",
foo() {
console.log( "obj2.foo:", this.name );
},
bar() {
console.log( "obj2.bar:", this.name );
}
},
handlers = {
get(target,key,context) {
if (Reflect.has( target, key )) {
return Reflect.get(target, key, context);
}
else {
for (var P of target[Symbol.for( "[[Prototype]]" )]) {
if (Reflect.has( P, key )) {
return Reflect.get(P, key, context);
}
}
}
}
},
obj3 = new Proxy({
name: "obj-3",
baz() {
this.foo();
this.bar();
}
},handlers);
obj3[Symbol.for("[[Prototype]]")] = [obj1, obj2];
obj3.baz();
//obj1.foo:obj-3
//obj2.bar:obj-3
类和对象
- 基本定义和生成实例
/ 基本定义和生成实例
// 继承
class Parent{
constructor(name='Lili'){
this.name = name;
}
}
let v_parent = new Parent('v');
console.log(v_parent);
class Child extends Parent{
}
console.log(new Child())
2.继承更改构造方法
class Parent{
constructor(name='Lili'){
this.name = name;
}
}
let v_parent = new Parent('v');
class Child extends Parent{
constructor(name='child'){
super(name);//一定放在第一行
this.type='child';
}
}
console.log(new Child('hello'))
- 静态方法的属性
class Student {
//构造函数
constructor() {
console.log("I'm a student");
}
study() {
console.log('study');
}
//静态方法,不会被实例继承,只能通过类来调用
static read() {
console.log('Reading me');
}
}
// 静态属性
Student.type = 'test';
console.log(Student.type);
console.log(typeof Student);
let stu = new Student();
stu.study();
Student.read();
- setter和getter方法
class Parent{
constructor(name='Lili'){
this.name = name;
}
//longName是属性 而不是方法
get longName(){
return 'mk'+this.name;
}
set longName(value){
this.name = value;
}
}
let v = new Parent();
console.log(v.longName);
v.longName = 'hello';
console.log(v.longName);
promise
- es5中的回调函数
let ajax = function (callback) {
setTimeout(function () {
callback&&callback.call();
},1000)
};
ajax(function () {
console.log(1);
})
es6中的异步函数
let ajax = function () {
console.log(2);
return new Promise(function (resolve,reject) {
setTimeout(function () {
resolve();
},1000)
})
}
ajax().then(function () {
console.log('promise','3');
return new Promise(function (resolve,reject) {
setTimeout(function () {
resolve();
},1000)
})
}).then(function () {
console.log('4')
})
- promise中的捕捉异常
let ajax = function (num) {
console.log('执行4');
return new Promise(function (resolve,reject) {
if(num>5){
resolve();
}
else{
throw new Error('error')
}
})
}
ajax(2).then(function () {
console.log('log',6);
return new Promise(function (resolve,reject) {
setTimeout(function () {
resolve();
},2000)
})
}).catch(function (err) {
console.log('catch',err);
}).then(function () {
console.log('666');
})
3.promise.all
function loadImg(src) {
return new Promise((resolve,reject)=>{
let img = document.createElement('img');
img.src = src;
img.onload = function () {
resolve(img);
}
img.onerror = function (err) {
reject(err);
}
})
}
function showImg(imgs) {
imgs.forEach(function (img) {
document.body.appendChild(img);
})
}
Promise.all([
loadImg('http://pic37.nipic.com/20140113/8800276_184927469000_2.png'),
loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1561378636849&di=35f3727b81a0be5ab90142ff0418ee70&imgtype=0&src=http%3A%2F%2Ff.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F8d5494eef01f3a29f863534d9725bc315d607c8e.jpg'),
loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1561378636848&di=593e42c920d932afb03088d2f74f336c&imgtype=0&src=http%3A%2F%2Fh.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F4a36acaf2edda3ccdbe14ea90fe93901213f9236.jpg')
]).then(showImg);
promise.race
function loadImg(src) {
return new Promise((resolve,reject)=>{
let img = document.createElement('img');
img.src = src;
img.onload = function () {
resolve(img);
}
img.onerror = function (err) {
reject(err);
}
})
}
function showImg(img) {
document.body.appendChild(img);
}
Promise.race([
loadImg('http://pic37.nipic.com/20140113/8800276_184927469000_2.png'),
loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1561378636849&di=35f3727b81a0be5ab90142ff0418ee70&imgtype=0&src=http%3A%2F%2Ff.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F8d5494eef01f3a29f863534d9725bc315d607c8e.jpg'),
loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1561378636848&di=593e42c920d932afb03088d2f74f336c&imgtype=0&src=http%3A%2F%2Fh.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F4a36acaf2edda3ccdbe14ea90fe93901213f9236.jpg')
]).then(showImg);
iterator
使用格式为
arr[Symbol.iterator]()
let arr = ['hello','world'];
let map = arr[Symbol.iterator]();
console.log(map.next());//{value: "hello", done: false}
console.log(map.next());//{value: "world", done: false}
console.log(map.next());//{value: undefined, done: true}
for..in内部使用的也是iterator,但是我们可以改写
let obj = {
start:[1,3,2],
end:[7,5,6],
[Symbol.iterator](){
let self = this;
let index = 0;
let arr = self.start.concat(self.end);
let len = arr.length;
return{
next(){
if(index < len){
return{
value:arr[index++],
done:false
}
}
else{
return{
value: arr[index++],
done:true
}
}
}
}
}
}
for (let key of obj){
console.log(key);//1 3 2 7 5 6
}
let arr = ['hello','world'];
for(let value of arr){
console.log('value',value);
}
genertaor
generator与函数的区别是,可以返回多次,yield也可以返回,写法是
function *() {}
let tell = function *() {
yield 'a';
yield 'b';
return 'c'
}
let k = tell();
console.log(k.next());
console.log(k.next());
console.log(k.next());
console.log(k.next());
let obj = {};
obj[Symbol.iterator] = function *() {
yield 1;
yield 2;
yield 3;
}
for (let key of obj){
console.log(key);//1 2 3
}
使用场景
// 定时从服务端取状态 长轮询
let ajax = function *() {
yield new Promise(function (resolve,reject) {
setTimeout(function () {
resolve({code:0})
},3000)
})
}
//只要取得不为0 就每秒查询一次 指导取到0
let pull = function () {
let genertaor = ajax();
let step = genertaor.next();
throw step.value.then(function (d) {
if(d.code!=0){
setTimeout(function () {
console.log('wait');
pull()
},1000)
}
else{
console.log(d);
}
})
}
pull();