ES6

312 阅读15分钟

let和const

  1. let和const有块级作用域
  2. 变量不能重复let定义
    let a = 1;
    let a = 2;//报错
  1. const定义时就要赋值
  2. const常量名称应该是全大写
  3. 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.`

解构赋值

  1. 数组结构赋值√
  • 直接赋值
    [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];
  1. 对象解构赋值√
  • 通过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. 字符串解构赋值
  2. 布尔值解构赋值
  3. 函数参数解构赋值√
{
    //  代码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]
}
  1. 数值解构赋值

正则表达式

  1. 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也是新增的,用于获取表达式范围
  1. 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
  1. 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
  1. s修饰符
    s修饰符 es6中没有实现 功能是处理换行等字符

字符串处理

  1. 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
  1. Unicode转字符
console.log(String.fromCharCode('0x20bb7'));//ஷ    es5
    console.log(String.fromCodePoint('0x20bb7'));//𠮷  es6
  1. 字符串遍历

    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
    }
  1. 判断字符串中是否包含指定字符
let str = 'string';
    console.log(str.includes('r'));//true 是否包含
    console.log(str.startsWith('str'));//true 是否以其开头
    console.log(str.endsWith('ng'));//true 是否以其结尾
  1. 重复字符串指定次
let str = 'abc';
    console.log(str.repeat(4));//abcabcabcabc
  1. 字符串拼接
let name = 'Lili';
    let info = 'Hello World';
    let m = `My name is ${name},I said "${info}"`;
  1. 字符串补齐
 let str = '3';
    console.log('1',str.padStart(2,'0'));//向前补(时间)
    console.log('2',str.padEnd(2,'0'));//向后补
  1. 定义字符串拼接方法
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
    }
  1. raw处理转义斜杠
    console.log(String.raw`Hi\n${1+2}`);//Hi\n3  raw对所有的斜杠进行了转义
    console.log(`Hi\n${1+2}`);//Hi(换行)3

数值处理

  1. 进制处理
console.log(0b1101111);//111 二进制
    console.log(0o157);//111 八进制
    console.log(111);//111 十进制
    console.log(0x6F);//111 十六进制
  1. 判断数是否是有尽的
console.log('15',Number.isFinite(15));//true
    console.log('NaN',Number.isFinite(NaN));//false
    console.log('1/0',Number.isFinite(1/0));//false
  1. 判断是否是数(是数返回false)
 console.log('NaN',Number.isNaN(NaN));//true
    console.log('0',Number.isNaN(0));//false
  1. 判断是否是整数 会将小数转为整数 不会将字符串转为数值
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 不会将字符串转为数值
  1. 最大值和最小值
//-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
  1. 返回浮点数的整数部分
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 四舍五入
  1. 判断是正数 负数 还是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
  1. 立方根
console.log('-1',Math.cbrt(-1));//-1
    console.log('64',Math.cbrt(64));//4

数组处理

  1. 将一系列数值转为数组
let arr = Array.of(3,4,7,9,11);
    console.log(arr);//[3, 4, 7, 9, 11]
    let empty = Array.of();
    console.log(empty);//[]
  1. 将伪数组或可遍历数组转为真数组
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]
  1. 数组中的替换
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(被覆盖位置开始,开始取的位置,结束取的位置)
  1. 数组遍历
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
    }
  1. 数组查找
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 找到的第一个的下标
    }))
  1. 判断数组中是否包含查找的元素
 console.log('number',[1,2,NaN,'a',4].includes(4));//true
    console.log('number',[1,2,NaN,'a',4].includes(NaN));//true

函数处理

  1. 函数入参设置默认值
function test(x,y = 'world',c) {
        console.log('默认值',x,y,c)
    }
    test('hello');// hello world undefined
    test('hello','Lili','11');//hello Lili 11
  1. 入参默认值是变量时,如果入参内有,就取入参内的,如果入参内没有,就去外面的
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();
  1. 当入参个数不确定时,如何获取所有入参
function test(...args) {
        for(let v of args){
            console.log(v);// 1 2 3 4 'a'
        }
    }
    test(1,2,3,4,'a');
  1. 数组转为离散值
    console.log(...[1,2,3]);//1 2 3
  1. 箭头函数
let arrow = v => v*2;
    console.log(arrow(3));//6
    let arrow2 = () => 5;
    console.log(arrow2(3));//5
  1. 伪调用
//    使用场景: 某一个功能依赖另一个功能 或者重复嵌套
    function tail(x) {
        console.log('tail',x);
    }
    function fx(x) {
        return tail(x);
    }
    fx(123);

对象处理

  1. 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  
  1. 对象属性处理
let a = 'b';
    let es5_obj = {
        a:'c'
    };
    let es6_obj = {
        [a]:'c'//会先进行计算
    }
    console.log(es5_obj,es6_obj);//{a:'c'} {b:'c'}
  1. 判断两个值(非对象)是否相等
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
  1. 拷贝(浅拷贝)
//    拷贝 assign(要拷贝到的值,拷贝的值)
//    浅拷贝 1.拷贝的只是地址 2.拷贝的是本身的属性,继承的属性不拷贝,不可枚举的属性也不会拷贝
    console.log('字符串',Object.assign({a:'a',b:'b'},{c:'c'}));//{a: "a", b: "b", c: "c"}
  1. 属性遍历
let test = {k:123,o:456};
    for(let [key,value] of Object.entries(test)){
        console.log(key,value)
    }

symbol类型处理

symbol 用symbol定义的基本类型 是不相等的(类似对象,不管值怎么样,地址永远不同)

  1. 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"}
  1. 有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

  1. 支持的数据类型不一样,weakSet的值必须是对象
  2. weakSet都是弱引用,即引用的都是地址,也不会检测这个地址是不是被垃圾回收掉了
  3. 有一些方法和属性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的区别

  1. 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都不那么方便

  1. 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

  1. 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
  1. 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

类和对象

  1. 基本定义和生成实例
/    基本定义和生成实例
//    继承
    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'))
  1. 静态方法的属性
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();
  1. 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

  1. 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')
    })
  1. 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();