ES6

300 阅读7分钟

1. var 特点

  1. 存在变量声明提升;
  2. 可重复声明变量;
  3. 全局变量挂载到window。

2.let

  1. 不会存在变量声明提升;
  2. 不能重复声明变量;
  3. 全局变量不会挂载到window;
  4. {}内形成块级作用域,产生临时死区,外部同名变量不能使用。

3. const

  1. 常量声明,声明时必须赋值且不能改变。
  2. 存储常量的空间里面的值不能改变。const PI = { } PI.name = 20 不会报错,这里修改的是对象中的值。
  3. 其余特点与let相同。

4. 拓展运算符+克隆

funcition sum(...arg){
	let sumNumber = 0;
	arg.forEach(function(ele){
        sumNumber += ele;
	});
	return sumNumber;
}
sum(1,2,5,7)

浅克隆1:

let obj1 = {
	name: 'cg'
}
let obj2 = {
    age:18
}
let obj3 = {
	...obj1,  //浅克隆
	...obj2
}

浅克隆2:Object.assign(targetObj,obj1,obj2)

深克隆1:

let obj1 = {
	name: 'cg',
	leader:{
        age:20
	}
}
let obj2 = {
    sex:famale
}
let obj3 = {
    ...obj1,
    leader:{    //深克隆
        ...leader
    },
    ...obj2
}

深克隆2:var obj = Json.parse(Json.stringify(obj1)) 该方法的问题:

  • 无法实现对函数、正则等特殊对象的克隆
  • 会抛弃对象的constructor,所有构造函数会执行Object
  • 对象有循环引用就会报错

5.destructring 解构

let obj = {
	name:'cst',
	age:18
}
let{ name , age } = obj; //解构
let{ name: oName, age: oAge , sex = 'male'} =  obj; //解构 
let { direct ,gut , mainActor, srceenwriter} = res.data; //解构

6.箭头函数

作用:函数目的指向性更强,可读性更好,简化代码,提升开发效率。

let sum = (a,b)=> a + b

特点:

  1. 不用写function关键字;

  2. 只能作为函数使用,不能做构造函数,没有原型。

  3. 函数形参不能重复;

  4. 返回值可以不写return,但是有时需要配合{}

  5. 内部arguments this定义时外围最接近一层的非箭头函数的arguments 和 this决定。

    let obj ={
    	ms:'ab',
    	fn(){
    		setTimeout()=>{
                console.log(this.msg)  //此处箭头函数this指向obj
    		}
    	}
    }
    obj.fn()
    

7.object.defineProperty

vue3.0- 数据双向绑定原理:object.defineProperty

object.defineProperty不能直接对数组进行设置,vue使用重写数组方法’

Object.defineProperty{obj,'name',{
    value:'cst',
    writable:false,
    configurable:true,
    enumerable:true,
    get:function(){
        return tem
    }, //get/set 与value和writable 不能同时使用
    set:function(val){
        tem = val;
    }
}}


var obj = {
	var tem= '';
    get name (){
        return tem
    },
    set name (newval){
        tem = enwval;
    }
}

数据劫持,

let oDiv = document.getElementById('show');
let oinput = document.getElementById('demo');
let oData = {
    prev: {
        name: 'marzot'
    },
    value: 'dizhongdi'
};
oinput.oninput = function () {
    oData.value = this.value;
}
let updata = () => oDiv.innerText = oData.prev.name;
updata();
监控对象属性是否改变
let Observer = (data) => { //传入Odata对象
    if (!data || typeof data != 'object') {
        return data;
    };
    Object.keys(data).forEach(function (keys) {
        //枚举对象的属性,然后循环操作
        definedRective(data, keys, data[keys]) //对象,属性,val
    });
}

let definedRective = (data, keys, val) => {
    Observer(val);//嵌套对象进行递归枚举。
    Object.defineProperty(data, keys, {
        get: function () {
            return val;
        },
        set: function (newVal) {
            if (newVal == val) return;
            val = newVal;
            updata();

        }
    })
}
Observer(oData);

oData.value = 'asgaga124154151515';
oData.prev.name = 'beiduofen';

8.proxy

proxy可以对新增的属性进行代理。Object.defineProperty不行。

let odata = {
    name: 'laowang',
    sex:{
        age:18
    }
}

let newdata = new Proxy (odata,{
    set(target,key ,val ,receiver){
        Reflect.set(target,key,val);
        updata();
    },
    get(target,key,receiver){ 
        return Reflect.get(target,key);
    },
    has(target,key){
       
    }
})

function updata(){
    console.log('更新了')

9.Class+继承

1.圣杯模式:

    function Father(){}
    function Son(){}
    Father.prototype.lastName=‘Jack‘;

    //圣杯模式
    function inherit(Target,Origin){
        function F(){};
        F.prototype=Origin.prototype;
        Target.prototype=new F();
    }

    inherit(Son,Father);
    var son=new Son();
    var father=new Father(); 

    Son.prototype.sex=‘male‘;
    console.log(son.lastName);//Jack
    console.log(son.sex);//male
    console.log(father.sex);//undefined

2. __proto__

Son.prototype.__proto__ = Father.prototype;

3. ES6API

Object.setPrototypeOf(Son,Father);

(需要降级浏览器才支持)

4. Class

  
    class Foo{
      static age = 'l00'  //静态属性
      static fly(){        //静态方法
        console.log('fly')
      }
      constructor(name){
        this.name = name|| '攻击机'; //私有属性
        this.blood = 100
      }
      biu(){
        console.log('biubiubiu') //原型方法/公有方法
      }
    }
    //实例
    var foo1 = new Foo('攻击机1');
    var foo2 = new Foo('攻击机2')
    //测试
    Foo.fly()//fly                  ->静态方法只属于类本身
    console.log(Foo.age)//100       ->静态属性只属于类本身
    console.log(foo1.name)//攻击机1 ->私有属性
    console.log(foo2.name)//攻击机2 ->私有属性
    console.log(foo1.blood)//100    ->私有属性
    console.log(foo2.blood)//100    ->私有属性
    foo1.biu()//biubiubiu           ->原型方法
    foo2.biu()//biubiubiu           ->原型方法
    //继承
    class Boom extends Foo{
      constructor(name){
        super(name)  //继承了私有属性
      }
    }
    //实例
    var boom1 = new Boom('轰炸机') 
    //测试
    Boom.fly()//fly                 ->继承父类的静态方法
    console.log(Boom.age)//100      ->继承父类的静态属性
    console.log(boom1.blood)//100   ->继承父类的私有属性
    console.log(boom1.name)//轰炸机 ->继承父类的私有属性
    boom1.biu()//biubiubiu          ->继承父类的原型方法

Class特点:

  1. 必须new;
  2. 不能枚举;
  3. 静态属性无法被实例继承,可以被super调用,可以被子类继承。

5.ES7-Class

需要配合插件 @bable/plugin-proposal-class-properties使用

静态属性 static num = 10

私有属性 property= 'xxx'

10. ES7-decorator

@ fn //装饰器 写在需要装饰的属性前面

function fn(proto,key,description){    
    description.writable = false;
    description.initializer = function(){ //修饰静态属性时initializer 修饰原型方法时为value
        //可以在这里做数据劫持
        return 'value';
    }
}

11. set

  1. 值唯一;
  2. 没有属性名,只有属性值;

用途:可以转成数组,其本身具备去重。交集。并集。差集的作用

let os = new Set(1,2,[44,84],true,{name:leo})
方法:
os.add(1,5,10)//添加值
os.delete(1)//删值
os.clear()//清空
os.has(1)//判断有无1
os.forEach(ele,val)=>{
    //遍历
}
for(let prop of os){  //for of 遍历
	console.log(prop)
}

应用场景:

数组转化:

let os = new Set(arr);
Array.from(os)//转换成数组
[...os]//拓展为数组

求并集

let arr1 = [1,2,5,8,];
let arr2 = [5,8,1,9];
let os = new Set(...arr1,...arr2);

求交集

let os1 = new Set(arr1);
let os2 = new Set (arr2);
let newArr = [...os1].filter(ele=>os2.has(ele))

求差

let os1 = new Set(arr1);
let os2 = new Set(arr2);
let newArr1 = [...os1].filter(ele=>!os2.has(ele))
let newArr2 = [...os2].filter(ele=>!os1.has(ele))
let newArr = [...newArr1,...newArr2]

12. map

let oMap = new Map()

方法:

oMap.get('name')//取值
oMap.set('name','leo')//赋值
oMap.delete('name')//删值
oMap.clear()//清空
oMap.size()//长度
oMap.forEach(key,value,self)=>{}//遍历
oMap.keys()//属性名
for(let prop of oMap){  //for of 遍历
	console.log(prop[0])
}

Map原理
function myMap() {
    this.bucketLength = 8;
    this.init();
}

myMap.prototype = {
    init: function () {
        this.bucket = new Array(this.bucketLength);
        for (var i = 0; i < this.bucket.length; i++) {
            this.bucket[i] = {
                type: 'bucket_' + i,
                next: null
            }
        }
    },
    makeHash: function (key) {
        let hash = 0;
        if (typeof key !== 'string') {
            if (typeof key == 'number') {
                hash = Object.is(key, NaN) ? 0 : key;
            } else if (typeof key == 'object') {
                hash = 1;
            } else if (typeof key == 'boolean') {
                hash = Number(key);
            } else {
                hash = 2;
            }
        } else {
            for (let i = 0; i < 3; i++) {
                hash += key[i] ? key[i].charCodeAt(0) : 0;
            }
        }
        return hash % 8;
    },
    set: function (key, value) {
        let hash = this.makeHash(key);
        let oTempBucket = this.bucket[hash];
        while (oTempBucket.next) {
            if (oTempBucket.next.key == key) {
                oTempBucket.next.value = value;
                return;
            } else {
                oTempBucket = oTempBucket.next;
            }
        };
        oTempBucket.next = {
            key: key,
            value: value,
            next: null
        };
    },
    get: function (key) {
        let hash = this.makeHash(key);
        let oTempBucket = this.bucket[hash];
        while (oTempBucket) {
            if (oTempBucket.key == key) {
                return oTempBucket.value;
            } else {
                oTempBucket = oTempBucket.next;
            }
        }
        return undefined;
    },
    delete: function (key) {
        let hash = this.makeHash(key);
        let oTempBucket = this.bucket[hash];
        while (oTempBucket.next) {
            if (oTempBucket.next.key == key) {
                oTempBucket.next = oTempBucket.next.next;
                return true;
            } else {
                oTempBucket = oTempBucket.next;
            }
        }
        return false;
    },
    has: function (key) {
        let hash = this.makeHash(key);
        let oTempBucket = this.bucket[hash];
        while (oTempBucket) {
            if (oTempBucket.next && oTempBucket.next.key == key) {
                return true;
            } else {
                oTempBucket = oTempBucket.next;
            }
        }
        return false;
    },
    clear: function (key) {
        this.init();
    }
}

let oMp = new myMap();
let obj1 = {
    name: 'cst'
}
oMp.set('name1', 'cst1');
oMp.set('name2', 'cst2');
oMp.set(obj1, '---');
oMp.set(obj1, '+++');
oMp.set(function () { }, true);

13.promise

1.异步编程:

定时器、事件、ajax 、文件读取。

异步编程的问题:

  1. 异步编程避免不了回调。易产生回调地狱,难于维护和扩展。
  2. try catch 只能捕获同步代码中出现的异常。
  3. 同步并发的异步存在一定的问题。

管理回调的方法:

  1. jquery callback
  2. Loadsh after
  3. promise
  4. generator
  5. async await

2.promise使用

let op = new Promise((resolve,reject)=>{  //同步执行
    
})
op.then(()=>{},()=>{})  异步执行 promise内部为微任务,有优先执行权,定时器,ajax为宏任务,会优先进入执行栈,但是会在promise后执行。

3.链式操作法则

let op = new Promise((resolve,reject)=>{}) 
op.then(()=>{  
},()=>{
    
}).then(()=>{ //链式操作
},()=>{ 
})

  1. 上一个promise不抛出错误时,下一个then执行resolve函数;
  2. 上一个promise抛出错误时,下一个then执行reject函数;
  3. 返回值可以作为下一个then注册函数的执行参数;
  4. 当返回值是 new promise对象时,下一个执行函数由new promise对象内部执行的函数决定。

4.API

promise.all([promise1,promise2,promise3]).then((resolve)=>{ 
	//三个promise对象都执行成功时,then执行成功回调函数
},(reject)=>{
    //有一个promise对象执行失败时,then执行失败回调函数
})

promise.race([promise1,promise2,promise3]).then((resolve)=>{ 
	//有一个执行成功时,then执行成功回调函数
},(reject)=>{
    //所有promise对象执行失败时,then执行失败回调函数
})

5. promise实现

function MyPromise (executor) {
    var self = this;
    self.status = 'pending';
    self.resolveValue = null;
    self.rejectReason = null;
    self.ResolveCallBackList = [];
    self.RejectCallBackList = [];

    function resolve (value) {
        if (self.status === 'pending') {
            self.status = 'Fulfilled';
            self.resolveValue = value;
            self.ResolveCallBackList.forEach(function (ele) {
                ele();
            });
        }  
    }

    function reject (reason) {
        if (self.status === 'pending') {
            self.status = 'Rejected';
            self.rejectReason = reason;
            self.RejectCallBackList.forEach(function (ele) {
                ele();
            });            
        }  
    }
    
    try {
        executor(resolve, reject);
    }catch(e) {
        reject(e);
    } 
};
function ResolutionRetrunPromise (nextPromise, returnValue, res, rej) {
    if (returnValue instanceof MyPromise) {
        // Promise 对象
        returnValue.then(function (val) {
            res(val);
        }, function (reason) {
            rej(reason)
        });
    }else {
        res(returnValue);
    }
}

MyPromise.prototype.then = function (onFulfilled, onRejected) {
    if (!onFulfilled) {
        onFulfilled = function (val) {
            return val;
        }
    }
    if (!onRejected) {
        onRejected = function (reason) {
            throw new Error(reason);
        }
    }    
    var self = this;

    var nextPromise = new MyPromise(function (res, rej) {
        if (self.status === 'Fulfilled') {
            setTimeout(function () {
                try {
                    // var nextResolveValue = onFulfilled(self.resolveValue);
                    // res(nextResolveValue);
                    var nextResolveValue = onFulfilled(self.resolveValue);
                    ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej);
                }catch(e) {
                    rej(e);
                }

            }, 0);
        }
    
        if (self.status === 'Rejected') {
            setTimeout(function () {
                try {
                    var nextRejectValue = onRejected(self.rejectReason);
                    ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej);
                }catch(e) {
                    rej(e);
                }

            }, 0);
        }
    
        // 
        if (self.status === 'pending') { 
            self.ResolveCallBackList.push(function () {
                try {
                    var nextResolveValue = onFulfilled(self.resolveValue);
                    ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej);
                }catch(e) {
                    rej(e);
                }
            });
    
            self.RejectCallBackList.push(function () {
                setTimeout(function () {
                    try {
                        var nextRejectValue = onRejected(self.rejectReason);
                        ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej);
                    }catch(e) {
                        rej(e);
                    }
                }, 0);
            });        
        }
    });
    return nextPromise;
};


MyPromise.race = function(promiseArr) {
    return new MyPromise(function (resolve, reject) {
        promiseArr.forEach(function (promise, index) {
           promise.then(resolve, reject);
        });
    });
};

14.generator 生成器

  let obj = {
        0: "a",
        1: "b",
        2: "c",
        length: 3,
        [Symbol.iterator]: function* () {
          let curIndex = 0;
          while (curIndex != this.length) {
            yield this[curIndex];
            curIndex++;
          }
        }
      };
      console.log([...obj])