一文搞懂ES6中的新技能

98 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

使用let定义变量

使用let定义的变量可以起到块级作用域的效果

    var i = 3
    for (var i = 0; i < 10; i++) {
        console.log(i);
    }
    console.log('最后i的值为:' + i); // 3

使用const定义常量

使用const定义的常量, 是不允许重新赋值进行修改的

当然如果是一个对象类型的常量, 则可以更改它里面的属性值

    const name = 'shaosiming'
    // name = 'dasiming' // error Assignment to constant variable.

    const car = {
        name: 'bmw',
        price: 40
    }
    car.name = 'byd' // const定义的对象, 可以修改它的属性值

结构化赋值

结构化的方法是为了把对象中的方法以及属性在赋给变量的过程中一次性做完

也就是程序会根据等号左侧的变量名去右侧寻找匹配项, 如果没有找到对应的匹配项, 则是undefined

    let person = {
        eat() {
            console.log('person eat');
        },
        sleep() {
            console.log('person sleep');
        }
    }

    // 正常写法
    // let eat = person.eat;
    // let sleep = person.sleep;

    // 结构化赋值
    // let {eat, sleep} = person;

    // 如果person里没有对应的方法或属性
    let {eat, sleep, hit, height} = person;

    eat();
    sleep();
    // hit() // 因为hit在person中不存在, 因此是undefined, 不能当函数调用
    console.log(hit); // undefined
    console.log(height); // undefined

    let {age='18', gender='male'} = person;
    console.log(age); // 18
    console.log(gender); // male

    function initData(data = {name: 'shaosiming', age: 18}) {
        console.log(data.name);
        console.log(data.age);
    }
    initData(); // shaosiming 18
    initData({name: 'dasiming', age: 20}); // dasiming 20

更便捷的字符串操作

我们可以使用forof对字符串中的每个字符进行遍历

也可以使用for循环把字符串当成一个字符数组来遍历

模板字符串, 也就是可以使用两个反引号, 来表示一个字符串, 这样字符串更加强大, 可以使用表达式, 可以换行, 还可以嵌套单引号或双引号而毫无问题

    // 对字符串进行遍历
    for (const c of 'shaosiming') {
        console.log(c);
    }

    let username = 'shaosiming'
    for (let i = 0; i < username.length; i++) {
        const c = username[i];
        console.log(c);
    }

    // 模板字符串``
    let myName = 'tianming'
    let sayHi = `hi, my name is ${name}, 
                what's 'your' "name"?`;
    console.log(sayHi);

proxy

Proxy(target, handler)是一个构造函数, target是被代理的对象, handler是包含对代理对象各种行为的对象

handler通常包括set方法和get方法

    // 代理
    let user = {
        name: 'shaosiming',
        age: 18
    }

    let userProxy = new Proxy(user, {
        set(target, key, value) {
            if (key === 'age' && (typeof value !== 'number')) {
                throw new Error('age属性必须是一个数值型数据');
            }
            console.log('set: ' + target + '-' + key + '-' + value);
            target[key] = value;
        },
        get(target, key) {
            console.log('get: ' + target + '-' + key);
            return target[key]
        }
    })

对数组的扩展

一个对象只要有length属性和0, 1, 2这个的属性就可以转换为数组

还可以使用...快速复制一个新的数组出来

    // 一个对象
    let data = {
        0: 'shaosiming',
        1: 'dasiming',
        length: 2
    }

    // 直接转换为数组
    let dataArr = Array.from(data)

    // 经过处理后转换为数据
    let dataArr2 = Array.from(data, function(item){
        return item += '!!!'
    })
    console.log(dataArr);
    console.log(dataArr2);

    let arr = [1, 2, 3, 4, 5];
    let arr2 = arr;
    arr2[2] = 30;
    console.log(arr); // arr和arr2是指向的同一个数组

    // 复制一个数组
    let arr3 = [...arr]
    arr3[3] = 40
    console.log(arr);
    console.log(arr3);  // arr和arr3指向的不同数组

对函数的扩展

箭头函数中, this指向的对象为定义时的对象, 而不是使用函数时的对象

普通函数中, this指向的对象为调用函数时的对象

因此对于下面的代码中, eat函数中的this指向调用者dog

而sleep函数中, this指向的对象为window

    // 普通函数
    let sayHello = function(name) {
        console.log('hi, ' + name);
    }

    // 箭头函数
    let sayHello2 = (name) => {
        console.log('hi, ' + name);
    }

    sayHello('shaosiming')
    sayHello2('dasiming')

    let dog = {
        name: 'laifu',
        eat() {
            console.log(this); // this指向调用者
            console.log(this.name + " eat");
        },
        sleep: _=>{
            console.log(this); // this指向window
            console.log(this.name + " sleep");
        }
    }
    dog.eat(); // laifu eat
    dog.sleep(); // sleep

对于对象的扩展

在定义对象属性的时候, 如果冒号两边一样, 就可以简写

如果属性名是一个常量时, 可以简写

如果属性名是一个变量时, 则不能使用简写形式, 而得使用[key]这种形式

    let catName = 'name'
    // let cat = {
    //     catName: catName // 冒号左边的catName其实是字符串'catName'
    // }

    // 可以简写为
    let cat = {
        catName // 当左右两边一样时可以这样简写
    }

    // 当属性名称是一个变量时
    let key = 'name'
    let cat2 = {
        [key]: 'shaosiming'
    }
    console.log(cat2);

promise

如果一个函数有async修饰, 其它函数内部才可以使用

执行规则如果一个async函数在执行时, 遇到await会先暂停, 直到异步操作完成, 才会继续执行

    // 麻烦写法
    new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() < 0.5) {
                value = '比较小的数';
                resolve(value);
            } else {
                value = '比较大的数'
                reject(value);
            }
        }, 2000);
    }).then(value => {
        console.log('then ' + value);
    }).catch(value => {
        console.log('catch ' + value);
    })

    // 简单写法
    function asyncTask() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    if (Math.random() < 0.5) {
                        value = '比较小的数';
                        resolve(value);
                    } else {
                        value = '比较大的数';
                        reject(value);
                    }
                }, 2000);
            })
    }

    async function execAsyncTask() {
        let res = await asyncTask();
        console.log(res);
    }
    execAsyncTask();