ES678...

192 阅读19分钟

ECMASript 6

let 关键字

let 关键字用来声明变量,使用 let 声明的变量有几个特点:
    1. 不允许重复声明
    2. 块级作用域(全局,函数,evalif-else)
    	{let j = 1;}在外部无法读取
    3. 不存在变量提升
    4. 不影响作用域链
    
 绑定多个按钮事件:
 for(var i = 0;i < it.length;i++)        //i最后都是it.length,无法监听点击事件
 for(let i = 0;i<items.length;i++){
            items[i].onclick = function(){
                //修改当前元素的背景颜色
                items[i].style.background = 'pink';
                console.log(i);   //当前点击的index
            }
            console.log(i);
        }
    
**应用场景:以后声明变量使用 let 就对了**

const 关键字

const 关键字用来声明常量,const 声明有以下特点:
    1. 声明必须赋初始值
    2. 标识符一般为大写
    3. 不允许重复声明
    4. 值不允许修改,添加可以
    5. 块级作用域
    
**注意: 对象属性修改和数组元素变化不会出发 const 错误,因为指向地址未改变**

**应用场景:声明对象类型使用 const,非对象类型声明选择 let****

变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。 
  
//数组的解构赋值,一一对应
const arr = ['张学友', '刘德华', '黎明', '郭富城'];
let [zhang, liu, li, guo] = arr;

//对象的解构赋值
const lin = {
        name: '林志颖',
        tags: ['车手', '歌手', '小旋风', '演员']
    	eat:funcation(){
            console.log("hi");
        }
    };
let {name, tags,eat} = lin;
调函数:
let {eat} = lin;
eat();          //输出hi

//复杂解构
let wangfei = {
    name: '王菲',
    age: 18,
    songs: ['红豆', '流年', '暧昧', '传奇'],
    history: [
        {name: '窦唯'},
        {name: '李亚鹏'},
        {name: '谢霆锋'}
    ]
    };
let {
        songs: [one, two, three], 
        history: [first, second, third]
	} = wangfei;
console.log(two);//流年
console.log(songs);//报错,undefind

/**注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式**

模板字符串

/*模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
1. 字符串中可以出现换行符
2. 可以使用 ${xxx} 形式输出变量**/

// 定义字符串
let str = `<ul>
        <li>沈腾</li>
        <li>玛丽</li>
        <li>魏翔</li>
        <li>艾伦</li>
    </ul>`;
// 变量拼接
let star = '王宁';
let result = `${star}在前几年离开了开心麻花`;

/**注意:当遇到字符串与变量拼接的情况使用模板字符串**

简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

let name = '尚硅谷';
let slogon = '永远追求行业更高标准';
let improve = function () {
	console.log('可以提高你的技能');
}
//属性和方法简写
let atguigu = {
    //直接引用
    name,
    slogon,
    improve,
    //方法可直接写
    change() {
    	console.log('可以改变你')
    }
};

**注意:对象简写形式简化了代码,所以以后用简写就对了**

**2.6.**箭头函数

ES6 允许使用「箭头」(=>)定义函数。

/**1. 通用写法**/
let fn = (arg1, arg2, arg3) => {
	return arg1 + arg2 + arg3;
}

箭头函数的注意点:
1.如果形参只有一个,则小括号可以省略
2.函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
3.箭头函数 this 指向声明时所在作用域下 this 的值
 (call()方法(此方法可更改函数中的参)调用函数可改变函数内this的值,但箭头函数值不变(this))
 例如:
 	function getName(){
        console.log(this.name);
    }
	let getName2 = () => {
        console.log(this.name);
    }
    //设置 window 对象的 name 属性
    window.name = '尚硅谷';
	const school = {
        name: "ATGUIGU"
    }
    //直接调用
    getName();  //尚硅谷
	getName2(); //尚硅谷
	//call 方法调用
	getName.call(school); //ATGUIGU
    getName2.call(school);//尚硅谷

4.箭头函数不能作为构造函数实例化
5.不能使用 arguments(作用:保存实参)

/**2. 省略小括号的情况:形参有且仅有一个**/
let fn2 = num => {
	return num * 10;
};

/**3. 省略花括号的情况:只有一条语句,return必省**/
let fn3 = score => score * 20;
	
/**4. this指向声明时所在作用域中 this 的值**/
let fn4 = () => {
	console.log(this);
}
let school = {
    name: '尚硅谷',
    getName(){
        let fn5 = () => {
            console.log(this);
        }
        fn5();
    }
};

应用:
		//需求-1  点击 div 2s 后颜色变成『粉色』
        //获取元素
        let ad = document.getElementById('ad');
        //绑定事件
        ad.addEventListener("click", function(){
            //保存 this 的值
            // let _this = this;
            //注定时器的this指向window
            setTimeout(() => {
                //修改背景颜色 this
                // console.log(this);
                // _this.style.background = 'pink';
                this.style.background = 'pink';
                //箭头函数时,定时器中this指向声明时所在作用域下 this 的值
            }, 2000);
        });

        //需求-2  从数组中返回偶数的元素
        const arr = [1,6,9,10,100,25];
        // const result = arr.filter(function(item){
        //     if(item % 2 === 0){
        //         return true;
        //     }else{
        //         return false;
        //     }
        // });
        const result = arr.filter(item => item % 2 === 0);
        console.log(result);

// 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
// 箭头函数不适合与 this 有关的回调.  事件回调(如事件监听,此时指向外层作用域的this), 对象的方法(此时不再指向对象)
/**注意:箭头函数不会更改 **this** 指向,用来指定回调函数会非常合适**/

函数参数初始值

ES6 允许给函数参数赋值初始值

1.形参

具有默认值的参数, 一般位置要靠后(潜规则)

function add(a,c=10,b) {
     return a + b + c;
 }
 let result = add(1,2);
 console.log(result);   //NaN

2.与解构赋值结合

function connect({host="127.0.0.1", username,password, port}){
    console.log(host)
    console.log(username)
    console.log(password)
    console.log(port)
}
connect({
    host: 'atguigu.com',
    username: 'root',
    password: 'root',
    port: 3306
})

rest 参数

ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments(得到的为obj)

/**作用与 arguments 类似**/
function add(...args){
	console.log(args);
}
add(1,2,3,4,5);  //输出的是数组

/**rest 参数必须是最后一个形参**/
function minus(a,b,...args){
	console.log(a,b,args);
}
minus(100,1,2,3,4,5,19);

注意:**rest** 参数非常适合不定个数参数函数的场景

spread 扩展运算符

扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。

/**展开数组**/
let tfboys = ['a','b','c'];
function fn(){
	console.log(arguments);   
}
fn(...tfboys)    //等同于fn('a','b','c')

/**展开对象**/
let skillOne = {
	q: '致命打击',
};
let skillTwo = {
	w: '勇气'
};
let skillThree = {
	e: '审判'
};
let skillFour = {
	r: '德玛西亚正义'
};
let gailun = {...skillOne, ...skillTwo,...skillThree,...skillFour};
//{q: '致命打击', w: '勇气', e: '审判', r: '德玛西亚正义'}

//应用:
//1. 数组的合并 情圣  误杀  唐探
const kuaizi = ['王太利','肖央'];
const fenghuang = ['曾毅','玲花'];
// const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
console.log(zuixuanxiaopingguo);

//2. 数组的克隆
const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua];//  ['E','G','M']
console.log(sanyecao);

//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments

Symbol

1.Symbol 基本使用

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点:
1.Symbol 的值是唯一的,用来解决命名冲突的问题
2.Symbol 值不能与其他数据进行运算
3.Symbol 定义的对象属性不能使用 forin 循环遍历,但是可以使用Reflect.ownKeys 来获取对象的所有键名

//创建 Symbol
let s1 = Symbol();
console.log(s1, typeof s1);

//添加标识的 Symbol
let s2 = Symbol('尚硅谷');
let s2_2 = Symbol('尚硅谷');
console.log(s2 === s2_2);  //false

//使用 Symbol for 定义
let s3 = Symbol.for('尚硅谷');
let s3_2 = Symbol.for('尚硅谷');
console.log(s3 === s3_2);  //true

注: 遇到唯一性的场景时要想到 Symbol
如:
let game = {
	name:'俄罗斯方块',
    up: function(){},
    down: function(){}
};
let methods = {      //不知道game中是否已存在这两个方法,所以用Symbol
    up: Symbol(),
    down: Symbol()
};
game[methods.up] = function(){    //这样加进去不会矛盾
    console.log("我可以改变形状");
}
game[methods.down] = function(){
    console.log("我可以快速下降!!");
}
//以这种方式定义
let youxi = {
    name:"狼人杀",
    [Symbol('say')]: function(){
        console.log("我可以发言")
    },
    [Symbol('zibao')]: function(){
        console.log('我可以自爆');
    }
}

//数据类型USONB  you are so niubility 
// u  undefined
// s  string  symbol
// o  object
// n  null number
// b  boolean

2.Symbol 内置

除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。

class Person{
    static [Symbol.hasInstance](param){
        console.log(param);  //{}
        return false;
    }
}
let o = {};
console.log(o instanceof Person); //false

const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));   //[1,2,3[4,5,6]]

迭代器

遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

1. ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费
2. 原生具备 iterator 接口的数据(可用 for of 遍历)
    a) Array
    b) Arguments
    c) Set
    d) Map
    e) String
    f) TypedArray
    g) NodeList
3. 工作原理
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next 方法返回一个包含 value 和 done 属性的对象

//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧']
// 使用 for...of 遍历数组
for(let v of xiyou){
    console.log(v);
}
let iterator = xiyou[Symbol.iterator]()
//调用对象的next方法
console.log(iterator.next());//{value: '唐僧', done: false}
console.log(iterator.next());//{value: '孙悟空', done: false}
console.log(iterator.next());//{value: '猪八戒', done: false}
console.log(iterator.next());//{value: '沙僧', done: false}

//自定义遍历
const banji = {
    name: "终极一班",
    stus: [
        'xiaoming',
        'xiaoning',
        'xiaotian',
        'knight'
    ],
    [Symbol.iterator]() {
        //索引变量
        let index = 0;
        //也可用箭头函数
        let _this = this;
        return {
            //迭代器
            next: function () {
                if (index < _this.stus.length) {
                    const result = { value: _this.stus[index], done: false };
                    //下标自增
                    index++;
                    //返回结果
                    return result;
                }else{
                    return {value: undefined, done: true};
                }
            }
        };
    }
}
//遍历这个对象 
for (let v of banji) {
    console.log(v);//xiaoming xiaoning xiaotian knight
}

**注: 需要自定义遍历数据的时候,要想到迭代器。**

生成器

生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
//异步编程  纯回调函数  文件操作 网络操作(ajax, request) 数据库操作
/**1.举例**/
function * gen(){
    console.log(111);
    yield '一只没有耳朵';
    console.log(222);
    yield '一只没有尾部';
    console.log(333);
    yield '真奇怪';
    console.log(444);
}
let iterator = gen();
console.log(iterator.next());         
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//111 {value: '一只没有耳朵', done: false}
//222 {value: '一只没有尾部', done: false}
//333 {value: '真奇怪', done: false}
//444 {value: undefined, done: true}

/**2.传参**/
function * gen(arg){
    console.log(arg);
    let one = yield 111;
    console.log(one);
    let two = yield 222;
    console.log(two);
    let three = yield 333;
    console.log(three);
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());  //AAA {value: 111, done: false}
console.log(iterator.next('BBB')); //BBB {value: 222, done: false}
//若仅仅
let iterator = gen('AAA');
console.log(iterator.next('BBB')); //AAA {value: 111, done: false}
console.log(iterator.next('CCC')); //CCC {value: 222, done: false}

/**3.应用**/
1s 后控制台输出 111  2s后输出 222  3s后输出 333 
        function one(){
            setTimeout(()=>{
                console.log(111);
                iterator.next();
            },1000)
        }
        function two(){
            setTimeout(()=>{
                console.log(222);
                iterator.next();
            },2000)
        }
        function three(){
            setTimeout(()=>{
                console.log(333);
                iterator.next();
            },3000)
        }
        function * gen(){
            yield one();
            yield two();
            yield three();
        }
        //调用生成器函数
        let iterator = gen();
        iterator.next();

/**4.实例**/
 //模拟获取  用户数据  订单数据  商品数据 
function getUsers(){
    setTimeout(()=>{
        let data = '用户数据';
        //调用 next 方法, 并且将数据传入
        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 getUsers();
    let orders = yield getOrders();
    let goods = yield getGoods();
}
//调用生成器函数
let iterator = gen();
iterator.next();

代码说明:
1. * 的位置没有限制
2. 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
3. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
4. next 方法可以传递实参,作为 yield 语句的返回值

Promise

Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

1.Promise 基本语法

//实例化 Promise 对象
const p = new Promise(function(resolve, reject){
    setTimeout(function(){
        // let data = '数据库中的用户数据';
        // 调用resolve则为成功,则会调用then方法,value就为data
        // resolve(data)
        let err = '数据读取失败';
        //调用reject为失败,调用then,传入reason
        reject(err);
    }, 1000);
})
//调用 promise 对象的 then 方法里的回调函数,value为成功的
p.then(function(value){
    console.log(value);
}, function(reason){
    console.error(reason);
})

2.Promise封装读取文件

//1. 引入 fs 模块
const fs = require('fs');

//2. 调用方法读取文件
// fs.readFile('./resources/为学.md', (err, data)=>{
//     //如果失败, 则抛出错误
//     if(err) throw err;
//     //如果没有出错, 则输出内容
//     console.log(data.toString());
// });

//3. 使用 Promise 封装
const p = new Promise(function(resolve, reject){
    fs.readFile("./resources/为学.mda", (err, data)=>{
        //判断如果失败
        if(err) reject(err);
        //如果成功
        resolve(data);
    });
});

p.then(function(value){
    console.log(value.toString());
}, function(reason){
    console.log("读取失败!!");
});

3.Promise封装Ajax

// 接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
    //1. 创建对象
    const xhr = new XMLHttpRequest()
    //2. 初始化
    xhr.open("GET", "https://api.apiopen.top/getJ")
    //3. 发送
    xhr.send()
    //4. 绑定事件, 处理响应结果
    xhr.onreadystatechange = function () {
        //判断
        if (xhr.readyState === 4) {
            //判断响应状态码 200-299
            if (xhr.status >= 200 && xhr.status < 300) {
                //表示成功
                resolve(xhr.response);
            } else {
                //如果失败
                reject(xhr.status);
            }
        }
    }
})

//指定回调
p.then(function(value){
    console.log(value);
}, function(reason){
    console.error(reason);
});

4.Promise.prototype.then

//创建 promise 对象
const p = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve('用户数据');
        // reject('出错啦');
    }, 1000)
})

//调用 then 方法  then方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果决定
//1. 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值为对象的成功的
 const result = p.then(value => {
     console.log(value);
     //1. 非 promise 类型的属性
     // return 'iloveyou';
     //2. 是 promise 对象
     // return new Promise((resolve, reject)=>{
			  //返回的成功或失败就是p的成功或失败
     //     // resolve('ok');
     //     reject('error');
     // });
     //3. 抛出错误 也是错误
     // throw new Error('出错啦!');
 }, reason=>{
     console.warn(reason);
 })

//链式调用 改变回调地狱现象
p.then(value=>{
    
},reson=>{}).then(value=>{
    
},reson=>{});

5.Promise.prototype.catch

const p = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        //设置 p 对象的状态为失败, 并设置失败的值
        reject("出错啦!");
    }, 1000)
})
// p.then(function(value){}, function(reason){
//     console.error(reason);
// })
p.catch(function(reason){
    console.warn(reason);
});

6.Promise实践

//引入 fs 模块
const fs = require("fs");

//回调地狱
// fs.readFile('./resources/为学.md', (err, data1)=>{
//     fs.readFile('./resources/插秧诗.md', (err, data2)=>{
//         fs.readFile('./resources/观书有感.md', (err, data3)=>{
//             let result = data1 + '\r\n' +data2  +'\r\n'+ data3;
//             console.log(result);
//         });
//     });
// });

//使用 promise 实现
const p = new Promise((resolve, reject) => {
    fs.readFile("./resources/为学.md", (err, data) => {
        resolve(data);
    });
});

p.then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/插秧诗.md", (err, data) => {
            resolve([value, data]);
        });
    });
}).then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/观书有感.md", (err, data) => {
            //压入
            value.push(data);
            resolve(value);
        });
    })
}).then(value => {
    console.log(value.join('\r\n'));
});

Set

ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:

  1. size 返回集合的元素个数
  2. add 增加一个新元素,返回当前集合
  3. delete 删除元素,返回 boolean 值
  4. has 检测集合中是否包含某个元素,返回 boolean 值
  5. clear 清空集合,返回 undefined
//创建一个空集合
let s = new Set();
//创建一个非空集合
let s1 = new Set([1,2,3,1,2,3]);
//集合属性与方法
//返回集合的元素个数
console.log(s1.size);
//添加新元素
console.log(s1.add(4));
//删除元素
console.log(s1.delete(1));
//检测是否存在某个值
console.log(s1.has(2));
//清空集合
console.log(s1.clear());

//实践
let arr = [1,2,3,4,5,4,3,2,1];
//1. 数组去重  (变成集合=>转为数组
let result = [...new Set(arr)];
console.log(result);
//2. 交集
let arr2 = [4,5,6,5,6];
let result = [...new Set(arr)].filter(item => {
    let s2 = new Set(arr2);// 4 5 6
    if(s2.has(item)){
        return true;
    }else{
        return false;
    }
});
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
console.log(result)
//3. 并集
let union = [...new Set([...arr, ...arr2])];
console.log(union)
//4. 差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);

Map

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:

  1. size 返回 Map 的元素个数
  2. set 增加一个新元素,返回当前 Map
  3. get 返回键名对象的键值
  4. has 检测 Map 中是否包含某个元素,返回 boolean 值
  5. clear 清空集合,返回 undefined
//创建一个空 map
let m = new Map();
//创建一个非空 map
let m2 = new Map([
        ['name','尚硅谷'],
        ['slogon','不断提高行业标准']
    ]);
    
//属性和方法
//获取映射元素的个数
console.log(m2.size);
//添加映射值
console.log(m2.set('age', 6));
//获取映射值
console.log(m2.get('age'));
//检测是否有该映射
console.log(m2.has('age'));
//清除
console.log(m2.clear());

class

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对

象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是

一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象

原型的写法更加清晰、更像面向对象编程的语法而已。

知识点:

  1. class 声明类
  2. constructor 定义构造函数初始化
  3. extends 继承父类
  4. super 调用父级构造方法
  5. static 定义静态方法和属性
  6. 父类方法可以重写
//父类
class Phone {
    //构造方法 名字不能修改
    constructor(brand, color, price) {
        this.brand = brand;
        this.color = color;
        this.price = price;
    }
    //方法必须使用该语法, 不能使用 ES5 的对象完整形式
    call() {
    	console.log('我可以打电话!!!')
    }
}
//子类
class SmartPhone extends Phone {
    constructor(brand, color, price, screen, pixel) {
        super(brand, color, price);
        this.screen = screen;
        this.pixel = pixel;
    }
    //子类方法
    photo(){
    	console.log('我可以拍照!!');
    }
    playGame(){
    	console.log('我可以玩游戏!!');
    }
    //方法重写
    call(){
    	console.log('我可以进行视频通话!!');
    }
    //静态方法
    static run(){
    	console.log('我可以运行程序')
    }
    static connect(){
    	console.log('我可以建立连接')
    }
}
//实例化对象
const Nokia = new Phone('诺基亚', '灰色', 230);
const iPhone6s = new SmartPhone('苹果', '白色', 6088,'4.7inch','500w');
//调用子类方法
iPhone6s.playGame();
//调用重写方法
iPhone6s.call();
//调用静态方法
SmartPhone.run();

//class的set和get
class Phone{
    get price(){
        console.log("价格属性被读取了");
        return 'iloveyou';
    }
    set price(newVal){
        console.log('价格属性被修改了');
    }
}
//实例化对象
let s = new Phone()
// console.log(s.price);
s.price = 'free';

数值扩展

1.二进制和八进制

ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示。

2.Number.isFinite()Number.isNaN()

Number.isFinite() 用来检查一个数值是否为有限的

Number.isNaN() 用来检查一个值是否为 NaN

3.Number.parseInt()Number.parseFloat()

ES6 将全局方法 parseIntparseFloat,移植到 Number 对象上面,使用不变。

4.Math.trunc

用于去除一个数的小数部分,返回整数部分。

5.Number.isInteger

Number.isInteger() 用来判断一个数值是否为整数

对象扩展

ES6 新增了一些 Object 对象的方法
    1. Object.is 比较两个值是否严格相等,与『===』行为基本一致(+0NaN2. Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象
    3. __proto__、setPrototypeOf、 setPrototypeOf 可以直接设置对象的原型
   		const school = {
            name: '尚硅谷'
        }
        const cities = {
            xiaoqu: ['北京','上海','深圳']
        }
        Object.setPrototypeOf(school, cities);
        console.log(Object.getPrototypeOf(school));
        console.log(school);

模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

1.模块化的好处

模块化的优势有以下几点:
    1. 防止命名冲突
    2. 代码复用
    3. 高维护性

2.模块化规范

ES6 之前的模块化规范有:
    1. CommonJS => NodeJSBrowserify
    2. AMD  => requireJS
    3. CMD  => seaJS
打包步骤:
1. 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
2. 编译 npx babel src/js -d dist/js --presets=babel-preset-env
3. 打包 npx browserify dist/js/app.js -o dist/bundle.js

引入NPM包(npm i jquery)
	import $ from'jquery';
	$('body').css('background','pink');

3.ES6 模块化语法

模块功能主要由两个命令构成:exportimport1. export 命令用于规定模块的对外接口
    2. import 命令用于输入其他模块提供的功能
    
	//1.统一暴露
	export{a,b,c}
    //2.默认暴露
    exports.default = {
        school: 'ATGUIGU',
        change: function change() {
            console.log("我们可以改变你!!");
        }
    };
	调用:m3.default.change();
	//3.分别暴露
	exports.teach = teach;
	var school = exports.school = '尚硅谷';
    function teach() {
        console.log("我们可以教给你开发技能");
    }

    //1. 通用的导入方式
    //引入 m1.js 模块内容
    import * as m1 from "./src/js/m1.js";
    //2. 解构赋值形式 
	//分别暴露和统一暴露(文件重名时,as后面跟的是别名)
    import {school, teach} from "./src/js/m1.js";
    import {school as guigu, findJob} from "./src/js/m2.js";
	//默认暴露(要有别名设置)
    import {default as m3} from "./src/js/m3.js";
    //3. 简便形式  仅针对默认暴露
    import m3 from "./src/js/m3.js";

ECMASript 7 新特性

Array.prototype.includes

Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
(indexOf返回的是下标,无则返回-1)

指数操作符

在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同

ECMASript 8 新特性

asyncawait

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

async 函数

1. async 函数的返回值为 promise 对象,
2. promise 对象的结果由 async 函数执行的返回值决定

//async 函数
async function fn(){
    // 返回一个字符串
    // return '尚硅谷';
    // 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise 对象
    // return;
    //抛出错误, 返回的结果是一个失败的 Promise
    // throw new Error('出错啦!');
    //返回的结果如果是一个 Promise 对象
    return new Promise((resolve, reject)=>{
        resolve('成功的数据');
        // reject("失败的错误");
    });
}
const result = fn();
//调用 then 方法
result.then(value => {
    console.log(value);
}, reason => {
    console.warn(reason);
})

await 表达式

1. await 必须写在 async 函数中
2. await 右侧的表达式一般为 promise 对象
3. await 返回的是 promise 成功的值
4. await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理

//创建 promise 对象
const p = new Promise((resolve, reject) => {
    // resolve("用户数据");
    reject("失败啦!");
})
// await 要放在 async 函数中.
async function main() {
    try {
        let result = await p;
        console.log(result);
    } catch (e) {
        console.log(e);
    }
}
//调用函数
main();

async和await结合读取文件

//1. 引入 fs 模块
const fs = require("fs");

//读取『为学』
function readWeiXue() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/为学.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readChaYangShi() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/插秧诗.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readGuanShu() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/观书有感.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

//声明一个 async 函数
async function main(){
    //获取为学内容
    let weixue = await readWeiXue();
    //获取插秧诗内容
    let chayang = await readChaYangShi();
    // 获取观书有感
    let guanshu = await readGuanShu();

    console.log(weixue.toString());
    console.log(chayang.toString());
    console.log(guanshu.toString());
}

main();

async与await封装AJAX请求

// 发送 AJAX 请求, 返回的结果是 Promise 对象
    function sendAJAX(url) {
        return new Promise((resolve, reject) => {
            //1. 创建对象
            const x = new XMLHttpRequest();
            //2. 初始化
            x.open('GET', url);
            //3. 发送
            x.send();
            //4. 事件绑定
            x.onreadystatechange = function () {
                if (x.readyState === 4) {
                    if (x.status >= 200 && x.status < 300) {
                        //成功啦
                        resolve(x.response);
                    }else{
                        //如果失败
                        reject(x.status);
                    }
                }
            }
        })
    }

    //promise then 方法测试
    // sendAJAX("https://api.apiopen.top/getJoke").then(value=>{
    //     console.log(value);
    // }, reason=>{})

    // async 与 await 测试  axios
    async function main(){
        //发送 AJAX 请求
        let result = await sendAJAX("https://api.apiopen.top/getJoke");
        //再次测试
        let tianqi = await sendAJAX('https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')
        console.log(tianqi);
    }
    main();

Object.values 和 Object.entries

1.  Object.values()方法返回一个给定对象的所有可枚举属性值的数组
2.  Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组

//获取对象所有的键
console.log(Object.keys(school));
//获取对象所有的值
console.log(Object.values(school));
//entries
console.log(Object.entries(school));
//创建 Map
const m = new Map(Object.entries(school));
console.log(m.get('cities'));

Object.getOwnPropertyDescriptors

该方法返回指定对象所有自身属性的描述对象

console.log(Object.getOwnPropertyDescriptors(school))
const obj = Object.create(null, {
     name: {
         //设置值
         value: '尚硅谷',
         //属性特性
         writable: true,
         configurable: true,
         enumerable: true
     } 
 });

ECMASript 9 新特性

Rest/Spread 属性

Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符

function connect({host, port, ...user}) {
    console.log(host);
    console.log(port);
    console.log(user);
}
connect({
    host: '127.0.0.1',
    port: 3306,
    username: 'root',
    password: 'root',
    type: 'master'
});

//对象合并
const skillOne = {
    q: '天音波'
}
const skillTwo = {
    w: '金钟罩'
}
const mangseng = {...skillOne, ...skillTwo};
console.log(mangseng)
// ...skillOne   =>  q: '天音波', w: '金钟罩'

正则表达式命名捕获组

ES9 允许命名捕获组使用符号『?<name>』,这样获取捕获结果可读性更强

let str = '<a href="http://www.atguigu.com">尚硅谷</a>';
//分组命名 提取 url 与 『标签文本』
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
//result = ["<a href=\"http://www.atguigu.com\">尚硅谷</a>","http://www.atguigu.com","尚硅谷"]
const result = reg.exec(str);
console.log(result.groups.url);    //result[1]
console.log(result.groups.text);   //result[2]

正则表达式反向断言

ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。

//声明字符串
let str = 'JS5211314你知道么 555啦啦啦';

//正向断言 \d:数字类型 ?=:是否为啦
const reg = /\d+(?=啦)/;
const result = reg.exec(str);  //[555]

//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);  
console.log(result);																//['555', index: 13, input: 'JS5211314你知道么555啦啦啦', groups: undefined]

****正则表达式 dotAll 模式

正则表达式中点.匹配除回车外的任何单字符,标记『s』改变这种行为,允许行终止符出现
//dot  .  元字符  除换行符以外的任意单个字符
let str = `
	<ul>
        <li>
            <a>肖生克的救赎</a>
            <p>上映日期: 1994-09-10</p>
        </li>
        <li>
            <a>阿甘正传</a>
            <p>上映日期: 1994-07-06</p>
        </li>
    </ul>`;
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){
data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);
[{title: '肖生克的救赎', time: '上映日期: 1994-09-10'},{title: '阿甘正传', time: '上映日期: 1994-07-06'}]

ECMASript 10 新特性

1.Object.fromEntries

//二维数组
const result = Object.fromEntries([
    ['name','尚硅谷'],
    ['xueke', 'Java,大数据,前端,云计算']
]);   									//{name: '尚硅谷', xueke: 'Java,大数据,前端,云计算'}

//Map
const m = new Map();
m.set('name','ATGUIGU');
const result = Object.fromEntries(m);    //{name: 'ATGUIGU'}

//Object.entries ES8
const arr = Object.entries({
    name: "尚硅谷"
})
console.log(arr);//[['name', '尚硅谷']] length==1

2.trimStart 和 trimEnd

let str = '   iloveyou   ';
console.log(str);               //   iloveyou   
console.log(str.trimStart());	//iloveyou 
console.log(str.trimEnd());		//   iloveyou

3.Array.prototype.flatflatMap

//flat 平
//将多维数组转化为低维数组
// const arr = [1,2,3,4,[5,6]];				//[1, 2, 3, 4, 5, 6]
// const arr = [1,2,3,4,[5,6,[7,8,9]]];     //[1, 2, 3, 4, 5, 6, 7, 8, 9]
//参数为深度 是一个数字
console.log(arr.flat(2));  

//flatMap
const arr = [1,2,3,4];
const result = arr.flatMap(item => [item * 10]);
console.log(result);            //[10,20,30,40]

4.Symbol.prototype.description

let s = Symbol('尚硅谷');
console.log(s.description);     //尚硅谷

ECMASript 11 新特性

1.String.prototype.matchAll

		let str = `<ul>
            <li>
                <a>肖生克的救赎</a>
                <p>上映日期: 1994-09-10</p>
            </li>
            <li>
                <a>阿甘正传</a>
                <p>上映日期: 1994-07-06</p>
            </li>
        </ul>`;
        //声明正则
        const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg
        //调用方法
        const result = str.matchAll(reg);
        console.log(result);		//egExpStringIterator {}
        // for(let v of result){
        //     console.log(v);
        // }

        // const arr = [...result];

        // console.log(arr);
//[["整个第一个li标签","肖申克的救赎","上映日期: 1994-09-10"],
// ["整个第二个li标签","阿甘正传","上映日期: 1994-07-06"]]

2.类的私有属性

		class Person{
            //公有属性
            name;
            //私有属性
            #age;
            #weight;
            //构造方法
            constructor(name, age, weight){
                this.name = name;
                this.#age = age;
                this.#weight = weight;
            }

            intro(){
                console.log(this.name);
                console.log(this.#age);
                console.log(this.#weight);
            }
        }

        //实例化
        const girl = new Person('晓红', 18, '45kg');

        // console.log(girl.name);
		//私有属性无法输出,控制台报错
        // console.log(girl.#age);			
        // console.log(girl.#weight);

        girl.intro();

3.Promise.allSettled

		//声明两个promise对象
        const p1 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品数据 - 1');
            },1000)
        });

        const p2 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品数据 - 2');
                // reject('出错啦!');
            },1000)
        });

        //调用 allsettled 方法
        const result = Promise.allSettled([p1, p2]);
        /** Promise {<pending>}
			[[Prototype]]: Promise
			[[PromiseState]]: "fulfilled"
			[[PromiseResult]]: Array(2)
			0: {status: 'fulfilled', value: '商品数据 - 1'}
			1: {status: 'fulfilled', value: '商品数据 - 2'}
			length: 2
        **/

        const res = Promise.all([p1, p2]);
        /**Promise
            [[Prototype]]:Promise
            [[PromiseState]]: "fulfilled"
            [[PromiseResult]]: Array(2)
                    0: "商品数据 - 1"
                    1: "商品数据 - 2"
            length: 2
        **/

4.可选链操作符

		// ?.
        function main(config){
            // const dbHost = config && config.db && config.db.host;
            const dbHost = config?.db?.host;

            console.log(dbHost);           //192.168.1.100
        }

        main({
            db: {
                host:'192.168.1.100',
                username: 'root'
            },
            cache: {
                host: '192.168.1.200',
                username:'admin'
            }
        })

5.**动态 **import 导入

btn.onclick = function(){
    import('./hello.js').then(module => {
        module.hello();						//hello文件下的hello()方法
    });
}