Skip to content

ECMAScript 6

let 和 const 【重要】

let 和 const 的作用如下:

  • 禁止重复声明
  • 块级作用域
  • 控制修改

相反, 用var声明的变量:可以重复声明、没有块级作用域、不能限制。

javascript
let a = "name";

const SCHOOL = "学校";

数组 解构

javascript
 let [a, b, c] = [1, 2, 3];
  • 解构的默认值:

    在解构赋值时,是允许使用默认值的。举例如下:

    javascript
    {
        //一个变量时
        let [foo = true] = [];
        console.log(foo); //输出结果:true
    }
    
    {
        //两个变量时
        let [a, b] = ['生命壹号']   //a 赋值为:生命壹号。b没有赋值
        console.log(a + ',' + b); //输出结果:生命壹号,undefined
    }
    
    
    {
        //两个变量时
        let [a, b = 'smyhvae'] = ['生命壹号']   //a 赋值为:生命壹号。b 采用默认值 smyhvae
        console.log(a + ',' + b); //输出结果:生命壹号,smyhvae
    }
  • undefined:相当于什么都没有,此时 b 采用默认值。

  • null:相当于有值,但值为 null。

对象 解构

jsx
    let { foo, bar } = { bar: '我是 bar 的值', foo: '我是 foo 的值' };
    console.log(foo + ',' + bar); //输出结果:我是键 foo 的值,我是键 bar 的值

上方代码可以看出,对象的解构与数组的结构,有一个重要的区别:数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,是根据键来取值的。

字符串 解构

字符串也可以解构,这是因为,此时字符串被转换成了一个类似数组的对象。举例如下:

javascript
const [a, b, c, d] = 'smyhvae';
console.log(a);//输出结果:s
console.log(b);
console.log(c);
console.log(d);

console.log(typeof a);  //输出结果:string

模板字符串

javascript
let str = `这是一个字符产`
console.log(str,typeof str)

let str = `<ul>
		<li></li>
		<li></li>
		</ul>`

字符串拼接

现在有了 ES6 语法,字符串拼接可以这样写:

javascript
    var name = 'smyhvae';
    var age = '26';

    console.log('name:'+name+',age:'+age);   //传统写法

    console.log(`name:${name},age:${age}`);  //ES6 写法

注意,上方代码中,倒数第二行用的符号是单引号,最后一行用的符号是反引号(在tab键的上方)。

箭头函数

1.this 是静态的. this始终指向函数声明时所在作用域下的this的值

2.不能作为构造实例化对象

3.不能使用 arguments 变量

定义和调用函数:(传统写法)

javascript
function fn1(a, b) {
    return a + b;
}

console.log(fn1(1, 2));  //输出结果:3

定义和调用函数:(ES6中的写法)

javascript
    let fn2 = (a, b) => {
        return a + b;
    };

    console.log(fn2(1, 2));  //输出结果:3

for ... of 循环

ES6 中,如果我们要遍历一个数组,可以这样做:

csharp
    let arr1 = [1, 2, 3, 4, 5];

    for (let value of arr1) {
        console.log(value);
    }

for ... of既可以遍历数组,也可以遍历Map对象。

参数默认值

传统写法

javascript
    function fn(param) {
        let p = param || 'hello';
        console.log(p);
    }

ES6 写法:(参数默认值的写法,很简洁)

javascript
    function fn(param = 'hello') {
        console.log(param);
    }

扩展运算符

注意区分:

  • 扩展运算符的格式为...
  • rest运算符的格式为...变量名
javascript
function fn(...arg) {   //当不确定方法的参数时,可以使用扩展运算符
    console.log(arg[0]);
    console.log(arg[1]);
    console.log(arg[2]);
    console.log(arg[3]);
}

fn(1, 2, 3); //方法中定义了四个参数,但只引用了三个参数,ES6 中并不会报错。

如果不想让 arr1 和 arr2 指向同一个内存地址,我们可以借助扩展运算符来做:

javascript
    let arr1 = ['www', 'smyhvae', 'com'];
    let arr2 = [...arr1];  //arr2 会重新开辟内存地址
    console.log('arr1:' + arr1);
    console.log('arr2:' + arr2);
    console.log('---------------------');

    arr2.push('你懂得');  //往arr2 里添加一部分内容
    console.log('arr1:' + arr1);
    console.log('arr2:' + arr2);

rest运算符

rest 在英文中指的是剩余部分(不是指休息)。我们来举个例子,理解剩余部分的含义:

javascript
    function fn(first, second, ...arg) {
        console.log(arg.length);
    }

    fn(0, 1, 2, 3, 4, 5, 6);  //调用函数后,输出结果为 5

从上方例子中可以看出,rest运算符适用于:知道前面的一部分参数的数量,但对于后面剩余的参数数量未知的情况。

字符串的扩展

ES6中的字符串扩展,用得少,而且逻辑相对简单。如下:

  • includes(str):判断是否包含指定的字符串
  • startsWith(str):判断是否以指定字符串开头
  • endsWith(str):判断是否以指定字符串结尾
  • repeat(count):重复指定次数

举例如下:

javascript
    let str = 'abcdefg';

    console.log(str.includes('a'));//true
    console.log(str.includes('h'));//false

    //startsWith(str) : 判断是否以指定字符串开头
    console.log(str.startsWith('a'));//true
    console.log(str.startsWith('d'));//false

    //endsWith(str) : 判断是否以指定字符串结尾
    console.log(str.endsWith('g'));//true
    console.log(str.endsWith('d'));//false

    //repeat(count) : 重复指定次数a
    console.log(str.repeat(5));

Number 的扩展

  • Number.isFinite(i):判断是否为有限大的数。比如Infinity这种无穷大的数,返回的就是false。
  • Number.isNaN(i):判断是否为NaN。
  • Number.isInteger(i):判断是否为整数。
  • Number.parseInt(str):将字符串转换为对应的数值。
  • Math.trunc(i):去除小数部分。

举例:

javascript
    //Number.isFinite(i) : 判断是否是有限大的数
    console.log(Number.isFinite(NaN)); //false
    console.log(Number.isFinite(5)); //true
    console.log(Number.isFinite(Infinity)); //false

    //Number.isNaN(i) : 判断是否是NaN
    console.log(Number.isNaN(NaN));//true
    console.log(Number.isNaN(5));//falsse

    //Number.isInteger(i) : 判断是否是整数
    console.log(Number.isInteger(5.23));//false
    console.log(Number.isInteger(5.0));//true
    console.log(Number.isInteger(5));//true

    //Number.parseInt(str) : 将字符串转换为对应的数值
    console.log(Number.parseInt('123abc'));//123
    console.log(Number.parseInt('a123abc'));//NaN

    // Math.trunc(i) : 直接去除小数部分
    console.log(Math.trunc(13.123));//13

Symbol

原始数据类型,表示独一无二的值,它是js语言的第七种数据类型,是一种类似于字符串的数据类型

特点:

  1. Symbol 的值是唯一的,用来解决命名冲突的问题
  2. Symbol 值不能与其他数据进行运算
  3. Symbol 定义的对象属性不能使用for...in循环遍历,但可以使用Reflect.ownKeys来获取对象的所有键名
javascript
//创建
let s = Symbol();
console.log(s, typeof s);  //--->Symbol()  "symbol"

let s2 = Symbol("字符串");
let s3 = Symbol("字符串");
console.log(s2===s3);  //--->false


//Symbol.for()创建
let s4 = Symbol.for("字符串");
console.log(s4, typeof s4)  //--->Symbol(字符串)  "symbol"
let s5 = Symbol.for("字符串");
console.log(s4===s5)  //--->true

向对象中添加方法 up down

JavaScript
let game = {}

let methods = {
    up: Symbol(),
    down :Symbol()
}
game[methods.up] = function(){}
game[methods.down] = function(){}


let youxi = {
    name:"youxi",
    [Symbol("say")]:function(){},
    [Symbol("look")]:function(){}
}

Symbol 内置值

ES6还提供了11个内置值

JavaScript
//类型检测
class Person{
    static [Symbol.hasInstance](parm){
        console.log("检测类型")
    }
}
//

迭代器

迭代器(Iterator)

生成器

生成器就是一个特殊的函数

异步编程,纯回调函数,node fs ajax mongodb

JavaScript
function * gen(){
    console.log("1111")
    yield '一只耳朵';
    console.log("222")
    yield '一直为八';
    console.log("333")
    yield '一只手'
}

let iterator = gen()
iterator.next()

生成器函数

JavaScript
function one(){
    setTimeout(()=>{
        console.log(111);
        iterator.next();
    },1000)
}
function two(){
    setTimeout(()=>{
        console.log(111);
        iterator.next();
    },2000)
}
function three(){
    setTimeout(()=>{
        console.log(111);
        iterator.next();
    },3000)
}
function * gen(){
    yield one();
    yield two();
    yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();

实例2

JavaScript
//模拟 用户数据 订单数据 商品数据
function getUser(){
    setTimeout(()=>{
        let data = "用户数据";
        iterator.next(data);
    },1000)
}
function getOrders(){
    setTimeout(()=>{
        let data = "订单数据";
        iterator.next(data);
    },1000)
}
function getGoods(){
    setTimeout(()=>{
        let data = "商品数据";
        iterator.next(data);
    },1000)
}
function * gen(){
    let users = yield getUser();
    console.log(users);
    let orders = yield getOrders();
    console.log(orders);
    let goods = yield getGoods();
    console.log(goods);
}
//调用生成器函数
let iterator = gen();
iterator.next();

ES6 Promise

JavaScript
function getNumber(){
//实例化 Promise 对象池
    const p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            var num = Math.ceil(Math.random()*10); //生成1-10的随机数
            if(num<=5){
                resolve(num);  //成功返回
            }
            else{
                reject('数字太大了');  //失败返回
            }
        }, 2000);
    });
    return p;            
}

getNumber()
.then(function(data){//成功
    console.log('resolved');
    console.log(data);
})
.catch(function(reason){//失败
    console.log('rejected');
    console.log(reason);
});


//3.使用Promise 封装
const p1 = new Promise(function(resolve,rej){
    let str = "囔波万!"
    resolve(str)
})

p1.then(res=>{
    return new Promise(function(resolve,rej){
        let str = "囔波吐!"
        resolve([res,str])
    })
}).then(res=>{
    return new Promise(function(resolve,rej){
        let str = "囔波思锐!"
        res.push(str)
        resolve(res)
    })
}).then(res=>{
    console.log(res);
}).catch(res=>{
    console.log("err");
})

resolve

成功返回的东西

reject

失败返回

then

成功无限链

catch

获取失败

Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

all

Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。

Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

race

all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法,

比如我们可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作,代码如下:

javascript
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
            resolve(img);
        }
        img.src = 'xxxxxx';
    });
    return p;
}

//延时函数,用于给请求计时
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('图片请求超时');
        }, 5000);
    });
    return p;
}

Promise
.race([requestImg(), timeout()])
.then(function(results){
    console.log(results);
})
.catch(function(reason){
    console.log(reason);
});

Set

JavaScript
//声明一个set
let s = new Set();
let s2 = new Set(["大的","小的","好的","坏的"]);

//元素个数
console.log(s2.size);
//添加新元素
s2.add("喜事儿");
//删除元素
s2.delete("坏的");
//检测
console.log(s2.has("好的"));
console.log(s2);
//清空
s2.clear();

Set实践

JavaScript
let arr = [1,2,3,4,5,6,7,2,3,4,2,2];
//1.数组去重
let result = [...new Set(arr)];
console.log(result);

//2.交集
let arr2 = [1,3,4,5];
let res = [...new Set(arr)].filter(item => new Set(arr2).has(item))

//3.并集
let union = [...new Set([...arr,...arr2])];

//4.差集
let diff = [...new Set(arr)].filter(item => !new Set(arr2).has(item))

Map

JavaScript
//声明 Map
let m = new Map();

//添加元素
m.set('name','名字');
m.set('change',function(){console.log("我们可以改变你")})
let key = {
    school : 'ATGUIGU'
}
m.set(key,['北京','上海','深圳']);
console.log(m);

//size
console.log(m.size);

//删除
m.delete('name');

//获取
console.log(m.get(key));

//清空
m.clear();

//遍历
for(let v of m){
    console.log(v);
}

Class 类

javascript

get set

数组的扩展

扩展1:Array.from()

javascript
    Array.from(伪数组/可遍历的对象)

作用:将伪数组或可遍历对象转换为真数组

扩展2:Array.of()

javascript
    Array.of(value1, value2, value3)

作用:将一系列值转换成数组。

扩展3:find() 和 findIndex()

方法1

javascript
    find(function(item, index, arr){return true})

作用:找出第一个满足「指定条件返回true」的元素。

方法2

javascript
    findIndex(function(item, index, arr){return true})

作用:找出第一个满足「指定条件返回true」的元素的index。

对象的扩展

扩展1(字符串判断)

javascript
    Object.is(v1, v2)

作用:判断两个数据是否完全相等。底层是通过字符串来判断的。

我们先来看下面这两行代码的打印结果:

javascript
        console.log(0 == -0);
        console.log(NaN == NaN);

打印结果:

bash
    true
    false

上方代码中,第一行代码的打印结果为true,这个很好理解。第二行代码的打印结果为false,因为NaN和任何值都不相等。

但是,如果换成下面这种方式来比较:

javascript
        console.log(Object.is(0, -0));
        console.log(Object.is(NaN, NaN));

打印结果却是:

bash
    false
    true

代码解释:还是刚刚说的那样,Object.is(v1, v2)比较的是字符串是否相等。

扩展2(合并源对象到一个对象)

javascript
    Object.assign(目标对象, 源对象1, 源对象2...)

作用: 将源对象的属性追加到目标对象上。如果对象里属性名相同,会被覆盖。

其实可以理解成:将多个对象合并为一个新的对象。

举例:

javascript
        let obj1 = { name: 'smyhvae', age: 26 };
        let obj2 = { city: 'shenzhen' };
        let obj3 = {};

        Object.assign(obj3, obj1, obj2);
        console.log(obj3);

扩展3:__proto__属性

举例:

javascript
       let obj1 = {name:'smyhvae'};
       let obj2 = {};

       obj2.__proto__ = obj1;

       console.log(obj1);
       console.log(obj2);
       console.log(obj2.name);

上方代码中,obj2本身是没有属性的,但是通过__proto__属性和obj1产生关联,于是就可以获得obj1里的属性。

模块化

语法

  • export
  • import

ECMAScript 8

async 和 await

async 和 await两种语法结合可以让异步代码像同步代码一样

async函数

  1. async函数的返回值为promise对象
  2. promise对象的结果由async函数执行的返回值决定
JavaScript
//async 函数
async function fn(){
    return "name"
}
const result = fn();

await表达式

  1. await必须写在async函数中
  2. await右侧的表达式一般为promise对象
  3. await返回的时promise成功的值
  4. await的promise失败了,就会抛出异常,需要通过try...catch捕获处理
JavaScript
//创建promise对象
const p = new Promise((resolve,reject)=>{
    resolve("成功");
})

//await 必须要放在 async函数中
async function main(){
    let rest = await p;
}

//调用函数
main();

async 和 await结合

JavaScript

ECMAScript 9

正则扩展

命名捕获分组

JavaScript
let str = '<a href="http://www.baidu.com">百度</a>'
const reg = /<a href="(?<url>.*)">(?<name>.*)<\/a>/;

const result = reg.exec(str);

console.log(result);
console.log(result.groups.url);

正向断言

根据后面的内容判断前面

javascript
let str = 'JS1245123你知道吗555拉拉拉'
const reg = /\d+(?=拉拉拉)/;

const result = reg.exec(str);

console.log(result);

反向断言

根据前面的内容判断后面

JavaScript
let str = 'JS1245123道吗555拉拉吗123'

const reg = /(?<=道吗)\d+/;
const result = reg.exec(str);
console.log(result);

dotAll模式

JavaScript

let str = `    <ul>
<li>
    <a href="">肖申克的救赎</a>
    <p>上映日期:1994-09-10</p>
</li>
<li>
    <a href="">阿甘正传</a>
    <p>上映日期:1994-07-06</p>
</li>
</ul>`

const reg = /<li>.*?<a href="">(.*?)<\/a>.*?<p>(.*?)<\/p>.*?<\/li>/gs;

//dot   .   元字符     除换行符以外的任意单个字符
let data = [];
while(result = reg.exec(str)){
    data.push({title:result[1],time:result[2]})
}
console.log(data);