ES6~ES11 新特性(尚硅谷)

ES


ES 全称是EcamScript ,是脚本语言的规范,而平时经常编写的JavaScript,是EcmaScript的一种实现,所以ES新特性其实指的就是JavaScript的新特性

ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制 造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994 年后该 组织改名为 Ecma 国际。

1.什么是 ECMAScript

ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言

ECMA-262

Ecma国际制订了许多标准,ECMA-262只是2其中一个,所有标准推荐:

Standards - Ecma International (ecma-international.org)

ECMA-262 历史

ECMA-262 - Ecma International (ecma-international.org)

注:从 ES6 开始,每年发布一个版本,版本号比年份最后一位大 1

1.5.谁在维护 ECMA-262

TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是 公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期 召开会议,会议由会员公司的代表与特邀专家出席

1.6.为什么要学习 ES6

ES6 的版本变动内容最多,具有里程碑意义

ES6 加入许多新的语法特性,编程实现更简单、高效

ES6 是前端发展趋势,就业必备技能

1.7.ES6 兼容性

http://kangax.github.io/compat-table/es6/ 可查看兼容性

babel就是用来做语法编译的,它可以将一些es6+的高级语法编译为浏览器可以识别的es5

2.ECMASript 6 新特性


2.1.let 关键字 let 关键字

用来声明变量,使用 let 声明的变量有几个特点:

  1. 不允许重复声明

  1. 块级作用域 【全局,函数,eval ——eval在es5的严格模式下才能使用】

let 声明的变量就是块级作用域变量只在代码块里有效,出代码块就无效了

循环语句中 if else while for 里面用let声明也是块级作用域

  1. 不存在变量提升

不允许在变量声明之前使用变量
eg: 
console.log(song);
letsong='aaa';
最终报错效果:UncaughtReferenceError: Cannotaccess'song'beforeinitializationat
  1. 不影响作用域链

作用域的集合就是作用域链(子集可以访问父集,父集不能访问子集)
    
    {
            letschool='尚硅谷';
            functionfn() {
         // 2.函数内部输出 ,下面没有向上一级寻找变量
                console.log(school);
            }
            // 1、调用函数 
            fn()
        }

应用场景:以后声明变量使用 let 就对了

补充内容:严格模式

严格模式是为JavaScript 定义了一种不同的解析与执行模型。在严格模式下,ECMAScript 3 中的一些不确定的行为将得到处理,而且对某些不安全的操作也会抛出错误。要在整个脚本中启用严格模式,可以在顶部添加如下代码:

"use strict";
es5严格模式定义

es5.0的严格模式:指的是es3.0和es5.0的冲突(共有)的部分的规则就叫es5.0的严格模式

也就是如果使用了es5.0的严格模式 那么es3.0和es5.0产生冲突的部分就使用es5.0 如果没有使用es5.0的严格模式 那就使用es3.0

为什么要使用es5严格模式

因为es3.0的代码更加松散,es5.0严格模式可以保证代码更加精准

声明函数
function函数的名字也是一个标识符,通过关键字function申明一个函数
function 函数名(){ 代码块 }
2.2 const声明常量及特点

const 关键字用来声明常量,const 声明有以下特点

  • 声明必须赋初始值

  • 标识符一般为大写

  • 不允许重复声明

  • 值不允许修改

  • 块儿级作用域

  • 对于数组和对象的元素修改,不算做对常量的修改,不会报错

注意: 对象属性修改和数组元素变化不会出发 const 错误

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

【常量数组元素发生了变化,但是地址没有发生变化】

constTEAM=['UZI','MXLG'.'Ming','Letme'];
TEAM.PUSH('Meiko');
2.3 变量的解构赋值

解构:就是进行拆分

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称 为解构赋值。

1.数组的解构

//数组的解构赋值

const arr = ['张学友', '刘德华', '黎明', '郭富城'];
let [zhang, liu, li, guo] = arr;

2.对象的解构

//对象的解构赋值
const lin = {
 name: '林志颖',
 tags: ['车手', '歌手', '小旋风', '演员']
};
let {name, tags} = lin;
//复杂解构
let wangfei = {
 name: '王菲',
 age: 18,
 songs: ['红豆', '流年', '暧昧', '传奇'],
 history: [
 {name: '窦唯'},
 {name: '李亚鹏'},
 {name: '谢霆锋'}
 ]
};
let {songs: [one, two, three], history: [first, second, third]} = 
wangfei

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

2.3 ES6--模板字符串

RS6 引入新的声明字符串的方式 【``】 ' ' " "

  1. 声明的一个格式

let str=`我也是一个字符串哦!`;

console.log(str, typeof str); // 打印模板字符串和对应的类型

模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:

1) 字符串中可以出现换行符

let str = `<ul>
         <li>沈腾</li>
         <li>玛丽</li>
         <li>魏翔</li>
         <li>艾伦</li>
 </ul>`;

2) 可以使用 ${xxx} 形式输出变量——可以进行变量的拼接

// 变量拼接
let star = '王宁';
let result = `${star}在前几年离开了开心麻花`;

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

2.4 ES6简化对象写法

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

let name = '尚硅谷';
let change = function () {
 console.log('可以提高你的技能');
}
//属性和方法简写
const school = {
 name,
 change,
 improve() {
 console.log('我们可以提高你的技能')
 }
}
2.5 ES6---箭头函数以及其声明特点

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

/**
* 1. 通用写法
*/
// 小括号里面是形参花括号里面是代码体
let fn = (arg1, arg2, arg3) => {
 return arg1 + arg2 + arg3;
}

箭头函数的特性:

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

箭头函数在全局作用域下声明时,this指向window

使用call 进行函数的调用 call 方法可以改变函数内部的值的   箭头函数的this值是静态的

箭头函数的注意点:

  • 如果形参只有一个,则小括号可以省略

  • 函数体如果只有一条语句,则花括号可以省略,花括号省略之后return 也需要进行省略,函数的返回值为该条语句的 执行结果

  • 箭头函数 注意:伪数组不能使用数组的方法 箭头函数的this是静态的

  • 箭头函数不能作为构造函数实例化对象

  • 注意:伪数组不能使用数组的方法

自定义函数
函数返回类型 函数名(参数,参数)

{

函数体;

}
构造函数   比较特殊的是构造寒暑期可以new()出一个新的函数,并在new的过程中初始化该函数
构造函数的特点:
    命名首字母大写。
    内部使用的this关键字,来指向即将要生成的实例对象。
    可以使用New来生成实例对象。
 new () 的过程中究竟发生了什么?
    创建一个新的对象。
    将关键字this指向这个新对象。
    执行构造函数里面的代码,并将构造函数里的属性和方法赋给这个新的对象的this。
    将this这个当前对象返回。
arguments 
只在函数中存在(箭头函数除外)
arguments 是一个伪数组
是一个集合,存储了我们传入的所参数
arguments具有length,可以通过下标访问
注意:伪数组不能使用数组的方法

使用arguments存储之后可以通过下标进行访问,比较简单

箭头函数的案例

补充知识:

 // 绑定点击事件   addEventListener() 方法用于向指定元素添加监听事件   
        /*参数说明
          addEventListener(参数1,参数2,参数3) 参数1,参数2是必填的 
          参数1:事件名称
          参数2:执行函数  function(){}
          参数3:触发·类型 布尔值 可控
        */
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>箭头函数的案例</title>
</head>

<body>
    <div id="ad"></div>
    <script>
        //一. 解决方法1:
        // 根据id找到对应的元素
        let ad = document.getElementById('ad');
        //    现在是在事件处理中,所以this指向的是div 
        ad.addEventListener("click", function () {
            // 需要保存this 的变量名  将外层作用域下面的this 进行了保存,保存之后当代码执行找不到this的时候就会往外层区域寻找
            let _this = this;
            //     setTimeout 设置一个定时器,该定时器在定时器到期后执行一个函数或指定一段代码
            setTimeout(function () {
                // 这里的this 指向windows,windows 没有 style 属性所以报错
                // 需要保存this 的变量名
                console.log(this);
                _this.style.background = "pink";
                // 这里的this指向
            }, 1000);
        })

        // 二.使用箭头函数的解决方法
        ad.addEventListener("click", function () {
            // 需要保存this 的变量名  将外层作用域下面的this 进行了保存,保存之后当代码执行找不到this的时候就会往外层区域寻找
            // let _this = this;
            //     setTimeout 设置一个定时器,该定时器在定时器到期后执行一个函数或指定一段代码
            /*使用箭头函数解决:箭头函数是静态的。指向函数在声明时作用域下面的this 的值
            */
            setTimeout(() => {
                // 这里的this 指向windows,windows 没有 style 属性所以报错
                // 需要保存this 的变量名
                // console.log(this);
                this.style.background = "pink";
                // 这里的this指向

            }, 1000);
        })
    </script>
</body>
<style>
    #ad {
        width: 100px;
        height: 100px;
        border: 1px solid #666;
        margin: 0 auto;
        background-color: #999;
    }
</style>
</html>

箭头函数案例2:

  <!-- 需求——2 从数组中返回偶数的元素 -->
    <script>
        const arr = [1.36, 9, 10, 100, 25];
        // 普通函数 
        const result = arr.filter(function (item) {
            return item % 2 === 0
        })
        console.log(result)
        // 使用箭头函数
        const result1 = arr.filter(item => item % 2 === 0)
        console.log(result1)
    </script>

箭头函数适合与this无关的回调,定时器,数组的方法回调

箭头函数不合适与this有关的事件回调,事件回调,对象方法

注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适

2.6 ES6——函数参数的默认值设置

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

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

当设置默认值时,如果没有传入对应元素的值就调用初始值

可以与解构赋值结合使用

2.7 rest参数

ES6 引入rest参数,用于获取函数的实参,用来代替arguments

arguments 可以获取函数在调用时的一些实参

ES5 获取实参的方式
function date(){
oconsole.log(arguments);
}
date('白芷','思慧','王一博');
// 上面的案例获取的是Object 对象
//ES6 rest参数 获取函数实参的方法   这里获取的数据是数组
function(...args){
console.log(args);  // 获取的结果是数组,可以使用数组的一些方法 filter some every map 
}
date('白芷','思慧','王一博');
~注意: rest 参数必须放到参数的最后~
eg: function fn(a,b,...args){}
2.8 ES6——spread扩展运算符
扩展运算符的写法: ...
扩展运算符能将【数组】转换为逗号分隔的【参数序列】
rest 参数在声明的时候是放在了函数声明的形参的位置
扩展运算法 【...】 使用的时候是放在了函数调用的实参的位置

【... 】 扩展运算符的案例

   const tfboys = ['易烊千玺', '王源', '王俊凯'];
        function chunwan() {
            console.log(arguments);
        }
        chunwan(...tfboys);   // chuwan('易烊千玺','王俊凯','王源')   可以转化为参数序列用逗号分隔
扩展运算符的应用
  1. 数组的合并

const a=['小米','大豆'];
const b=['学生','阿帆'];
const all=[...a, ...b];
console.log(all);   // (4) ['小米', '大豆', '学生', '阿帆']

2.数组的克隆

const one=['E','F','G'];
const two=[...one];  // ['E','F','G']
console.log(two)  

3.将伪数组转为真正的数组

<body>
    <div></div>
    <div></div>
    <div></div>
    <script>
        const divs = document.querySelectorAll('div');   
        console.log(divs);  // 这时获取的是一个对象
        const divArr = [...divs];
        console.log(divArr);   // 这时获取的是一个数组
    </script>
</body>
querySelectorAll() 非常便捷地获取文档中指定元素列表
eg:
const divs=document.querySelectorAll()
2.9 ES6——symnol

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。Symbol是ES6引入的一种新的数据类型

Symbol 特点 :

  • Symbol 的值是唯一的,用来解决命名冲突的问题

  • Symbol 值不能与其他数据进行运算

  • Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用 Reflect.ownKeys 来获取对象的所有键名

//创建 Symbol的方式
// ***********************创建symbol 的方式1: ***********************
let s = Symbol();
console.log(s, typeof s);
//添加标识的 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
数据类型:
USONB
u         undefined
s         string
o         object
n         null number
b         boolean
1. ES6——对象添加Symbol类型的属性

symbol 使用场景: 给对象添加属性和方法 表示独一无二的值

1.给对象添加方法方式一: 设置方法,通过方法进行合并

let game = {
    name : 'ran'
}

let methods = {
    up:Symbol()
    down:Symbol()
}
game[methods.up]=function(){
    console.log('aaa');
}
game[methods.down]=function(){
    console.log('bbb');
}
console.log(game)    // name: 'ran',Symbol(),Symbol()

2.给对象添加方法方式二:

let youxi = {
    name: '狼人杀',
    [Symbol('say')]:function(){
        console.log('阿萨德')
    }
}
console.log(youxi)    // name:'狼人杀',Symbol(say)
2. Symbol 内置值

除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法 【symbol 对象的属性】

Symbol.hasInstance 【自己企业控制类型检测】

当其他对象使用 instanceof 运算符,判断是否为该对 象的实例时,会调用这个方法

Symbol.isConcatSpreadable

对象的 Symbol.isConcatSpreadable 属性等于的是一个 布尔值,表示该对象用于 Array.prototype.concat()时, 是否可以展开。

Symbol.species

创建衍生对象时,会使用该属性

Symbol.match

当执行 str.match(myObject) 时,如果该属性存在,会 调用它,返回该方法的返回值。

Symbol.replace

当该对象被 str.replace(myObject)方法调用时,会返回 该方法的返回值。

Symbol.search

当该对象被 str.search (myObject)方法调用时,会返回 该方法的返回值。

Symbol.split

当该对象被 str.split(myObject)方法调用时,会返回该 方法的返回值。

Symbol.iterator

对象进行 for...of 循环时,会调用 Symbol.iterator 方法, 返回该对象的默认遍历器

Symbol.toPrimitive

该对象被转为原始类型的值时,会调用这个方法,返 回该对象对应的原始类型值。

Symbol. toStringTag

在该对象上面调用 toString 方法时,返回该方法的返 回值

Symbol. unscopables

该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。

控制对象在特定场景下的表现

2.10 迭代器

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

  1. ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费

  1. 原生具备 iterator 接口的数据(可用 for of 遍历)

a) Array

b) Arguments

c) Set

d) Map

e) String

f) TypedArray

g) NodeList

上面的一些数据都是部署了iterator接口

js中,我们所指的就是iterator接口就是对象里面的一个属性

3) 工作原理

  1. 创建一个指针对象,指向当前数据结构的起始位置

  1. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员 【返回对象的方法身上有 next方法】

  1. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员

  1. 每调用 next 方法返回一个包含 value 和 done 属性的对象

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

1.迭代器的应用
    //   声明一个对象
        const banji = {
            name: "终极一班",
            stus: [
                'xiaoming',
                'xiaowang',
                'xiaotian',
                'knight'
            ],
            //  2. 加上迭代器————迭代器返回的是一个对象————第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员 
            [Symbol.iterator]() {
                // 索引变量
                let index = 0;
                // 在外层声明变量进行保存
                let _this = this;
                return {
                    next: function () {
                        //根据下标决定返回的结果
                        if (index < _this.stus.length) {
                            // 每一次调用next方法,都返回的结果就是false,我们需要对返回结果进行处理
                            const result = { value: _this.stus[index], done: false };
                            // 让下标进行自增
                            index++;  // 不进行自增 永远为0
                            // 返回结果
                            return result;
                        } else {
                            return { value: undefined, done: true };
                        }

                    }
                };
            }
        }
        //1. 遍历这个对象
        for (let v of banji) {
            console.log(v);   //这里显示不能被迭代   
            // 要求使用 for...of... 进行遍历 返回的是数组里面的对象
        }
2.11生成器函数

生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同

// 声明的时候需要加 * 号
//  yield 函数代的分隔符 3个分隔符产生4块
function * gen(arg){
    console.log(arg);  // 参数传递
    // 可以出现 yield 语句
 yield '一只没有耳朵';
 yield '一只没有尾巴';
 return '真奇怪';
}
//  执行的时候需要借助【【 iterator 【迭代器】 是一个接口,为各种不同的数据结构提供统一的访问机制  】】
let iterator = gen('AAA');
console.log(iterator.next());   // 每调用一次执行第一段 并且对yield 语句后面的数据进行返回
console.log(iterator.next());   // 第二次调用的时候传入的实参将作为第一个yield 语句的整体返回结果
console.log(iterator.next())
注: next 方法在调用的时候是可以传入实参的  实参就是业务语句的返回结果

整体传参和next 方法传参,next里面传递的参数将作为上一个语句的返回结果

1.生成器函数的参数传递
// 整体传参
function * gen(arg){
    console.log(arg);
    }
let iterator = gen('AAA');

    // 使用next() 进行参数的传递
    iterator.next('AAA')    // 第二次调用的时候传入的实参将作为第一个yield 语句的整体返回结果

整个js是单线程的 ,异步也是单线程的 【文件操作, 网络操作(ajax, request) 数据库操作】

代码说明:

  • * 的位置没有限制

  • 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值

  • yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码

  • next 方法可以传递实参,作为 yield 语句的返回值

2.12 Promise基本介绍和使用

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

  • Promise 构造函数: Promise (excutor) {}

  • Promise.prototype.then 方法

  • Promise.prototype.catch 方法

I/O流简介
IO流:I的全称是Input,O的全称是Output。表示读取,流可以看做是程序传输数据的通道。

作用:解决程序请求资源,输出资源的问题。
异步编程主要是IO的代码 

异步编程解决回调地狱的问题

地狱不是只回调嵌套,而是嵌套之后,代码的可读性和调试性都降低了

1.promise 封装读取文件
// 1.首先:需要引入fs 模块
const fs=request('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/为学.md",(err.data)=>{
        // 判断如果失败 
        if(err)reject(err);
        // 如果成功 
        resolve(data);
    });
});
p.then(function(value){
console.log(value.toString());
},function(reason){
    console.log("读取失败")
});
2.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/getJoke");
    //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);
});
3.Promise——then 方法

then 方法用来指定回调

then 方法返回结果的状态
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 123;
    //2.是promise 对象
    // return new Promise((resolve, reject) => {
    //     //resolve('ok');
    //     reject('error')
    / });
    //3.抛出错Error
    throw new Error('出错啦!')
}, reason => {
    console.warn(reason);
});
console.log(result);

//也可以链式调用,嵌套异步任务,杜绝回调域

什么是fs模块

fs 模块是node.js的一个核心模块,专门用来操作系统中的文件,常用的操作方法是对文件的读取和写入使用require('fs'),载入fs模块,模块中所有方法都有同步和异步两种形式。异步方法中回调函数的第一个参数总是留给异常参数(exception),如果方法成功完成,该参数为null或者undefined 异步写法 demo 有一个回调函数

fs.readFile(文件路径,options,回调函数)
异步的读取指定路径的文件,回调函数在读取文件完成之后触发
4.Promise实践——读取多个文件
//引入fs模块
const fs = require("fs");
// 1. 读取多个文件的实现方法1:
//   fs.readFile('./hist.txt', (err, data1)=>{})    fs.readFile('文件路径', 回调函数)  回调地狱的问题:容易重名 重名之后不容易被发现,调试问题不方便
// fs.readFile('./hist.txt', (err, data1) => {
//     fs.readFile('./wx.txt', (err, data2) => {
//         fs.readFile('./sg.txt', (err, data3) => {
//             let result = data1 + '\r\n' + data2 + '\r\n' + data3 + '\n';
//             console.log(result);
//         });
//     });
// });

//读取多个文件的实现方法2: 使用promise 实现,不会产生回调地狱的现象
const p = new Promise((resolve, reject) => {
    fs.readFile("./hist.txt", (err, data) => {
        resolve(data);
    });
});

p.then(value => {
    // 这里不能在   fs.readFile("./wx.txt", (err, data) => {
    //      resolve([value, data]);
    // }); 里面继续嵌套,不然会出现回调地狱的问题,所以需要return 
    return new Promise((resolve, reject) => {   // 这里为什么药返回Promise  因为 不return promise 是返回undefined  只有返回promise 才能接着调用 then 实现链式调用 
        
        fs.readFile("./wx.txt", (err, data) => {
            resolve([value, data]);   // resolve 可以改变peomise 对象的状态的
        });
    })
}).then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./sg.txt", (err, data) => {
            //压入
            value.push(data);
            resolve(value);
        });
    })
}).then(value => {
    // join() 方法内部做了字符串的拼接
    console.log(value.join('\r\n'));
})

补充

buffer : Node.js 提供的一个二进制缓冲区,常用来处理 I/O 操作

5.Promise——catch方法
const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        //设置p对象的状态为失败,并设置失败的值
        reject("出错啦!");
    }, 1000)
});

// p.then(function (value) {}, function (reason) {
//     console.error(reason);
// });
// catch 可以理解为直接捕获错误  相当于then 填写失败回调
p.catch(function(reason){
    console.warn(reason);
})
2.13 Set (集合)

集合介绍ES6提供了新的数据结构Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator 接口【为各种不同的数据结构提供统一的访问机制】,所以可以使用【扩展运算符 ——(...)】和【for…of…】进行遍历,集合的属性和方法:1) size: 返回集合的元素个数2)add: 增加一个新元素,返回当前集合3)delete: 删除元素,返回boolean 值4)has : 检测集合中是否包含某个元素,返回boolean值

扩展运算符:就是三个点

//声明一个 set
let s = new Set();
let s2 = new Set(['大事儿', '小事儿', '好事儿', '坏事儿', '小事儿']);

//自动去重,只有一个'小事儿',相当于高中数学集合的互异性
console.log(s2);
console.log(s,typeof s);  // typeof s 输出数据的类型


//元素个数 
console.log(s2.size);

//添加新元素
s2.add('喜事儿');
console.log(s2);

//删除元素
s2.delete('坏事儿');
console.log(s2);

//检测
console.log(s2.has('中事儿'));

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

//清空集合
s2.clear();
console.log(s2);
集合实践
let arr1 = [1, 2, 3, 4, 5, 4, 3, 2, 1];

//1. 数组去重
let result1 = [...new Set(arr1)];
console.log(result1);

//2. 交集
let arr2 = [4, 5, 6, 5, 6];
// let result2 = [...new Set(arr1)].filter(item => {   【let result2=new Set(arr);  这个时候数组是一个集合 可以使用扩展运算符将集合变为一个数组 】
//     let s2 = new Set(arr2); // 4 5 6
//     if (s2.has(item)) {
//         return true;
//     } else {
//         return false;
//     }
// });
//简化
let result2 = [...new Set(arr1)].filter(item => new Set(arr2).has(item));
console.log(result2);

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

//4. 差集   差集中谁是主体结果是不一样的
let diff = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);

补充: 拓展运算符——它用于把一个数组转化为用逗号分隔的参数序列

2.24 Map 升级版的对象

ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator 接口,所以可以使用【扩展运算符】和【for…of…】进行遍历。Map的属性和方法:1)size:返回Map的元素个数2)set:增加一个新元素,返回当前Map3)get:返回键名对象的键值4)has:检测Map中是否包含某个元素,返回boolean值5)clear:清空集合,返回undefined

//声明 Map
let m = new Map();
//添加元素
m.set('name', '尚硅谷');
console.log(m);

m.set('change', function () {
    console.log("我们可以改变你!!");
});
console.log(m);

let key = {
    school: 'ATGUIGU'
};
m.set(key, ['北京', '上海', '深圳']);
console.log(m);

//元素个数
console.log(m.size);

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

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

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

//清空
m.clear();
console.log(m);
2.15 class 类
class介绍

ES6提供了更接近传统语言【java, c++】的写法,引入了Class (类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而己。知识点:

  • class 声明类

  • constructor 定义构造函数初始化

  • extends 继承父类

  • super 调用父级构造方法

  • static定义静态方法和属性

  • 父类方法可以重写

//es5(构造函数)
function Phone(brand, price) {
    this.brand = brand;
    this.price = price;
}
//添加方法
Phone.prototype.call = function () {
    console.log("我可以打电话!!");
}
//实例化对象
let Huawei = new Phone('华为', 5999);
Huawei.call();
console.log(Huawei);

//es6(class类)
class Shouji {
    //构造方法名字不能修改
    constructor(brand, price) {
        this.brand = brand;
        this.price = price;
    }
    //方法必须使用该语法,不能使用ES5 的对象完整形式
    call() {
        console.log("我也可以打电话!!");
    }
}
let onePlus = new Shouji("1+", 1999);
onePlus.call();
console.log(onePlus);

补充: 什么是语法糖:指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

显式原型: prototype

class类里面的静态成员
function Phone(){}   // 这是一个构造函数 构造函数本身也是一个对象 可以往对象上面添加属性和方法
Phone.name=手机;
Phone.change=function(){
    console.log("晚上好!")
}
注: 实例对象和函数对象的实例是不通的
function Phone() {
    }
Phone.name = '手机';
Phone.change = function () { //属于函数对象(静态成员,只有函数可以用)
    console.log("我可以改变世界");
}
Phone.prototype.size = '5.5inch'; //属于实例对象

let nokia = new Phone(); //实例对象和函数对象不相通        
console.log(nokia.name); //undefined
// nokia.change();
console.log(nokia.size); //5.5inch

class Phone2 {
    //静态属性
    static name = '手机'; //属于类的对象(静态成员,只有类可以用),不属于实例对象
    static change() {
        console.log("我可以改变世界");
    }
}
let nokia2 = new Phone2();
console.log(nokia2.name); //undefined
console.log(Phone2.name); //手机

上面的知识中涉及到了静态属性和实例属性

这里我们需要区别一下静态属性和实例属性的区别

1、静态属性是类自身的属性,只能在类自身调用,而实例属性是实例对象的属性;
2、实例对象无法调用静态属性,但类可调用实例属性;
3、静态属性只有一种声明方法,语法“类名.属性名=值”,而实例属性有多种声明方法,例类中用“属性名=值”定义。
实例: 在 面向对象程序设计中,“类”在实例化之后叫做一个“实例”。 “类”是静态的,不占进程内存,而“实例”拥有动态内存。
2.16 es5构造函数的继承
 使用构造函数来实现继承
//手机(父类)
function Phone(brand, price) {
    this.brand = brand;
    this.price = price;
}
Phone.prototype.call = function () {
    console.log("我可以打电话");
}

//智能手机(子类)
function SmartPhone(brand, price, color, size) {
    Phone.call(this, brand, price);
    this.color = color;
    this.size = size;
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone;
//SmartPhone.prototype.constructor = SmartPhone; //可加可不加
//声明子类的方法
SmartPhone.prototype.photo = function () {
    console.log("我可以拍照");
}
SmartPhone.prototype.playGame = function () {
    console.log("我可以玩游戏");
}

const chuiz = new SmartPhone('锤子', 2499, '黑色', '5.5inch');
console.log(chuiz);
console.log(chuiz.price);
chuiz.call();
chuiz.photo();
chuiz.playGame();
2.17 class类的继承 与 子类对父类方法的重写

构造方法

.构造方法是一个方法,但它一个特殊的方法,它没有返回值,即使是void型的值也不能够返回。它的任务就是为了对象初始化内部的状态

2.构造方法在创建对象时被系统调用(即自动调用,不需要程序员主动调用)。

3.构造函数当程序中包含有带参的构造函数时,系统将不会再提供的无参构造函数

[public] 构造方法名([形参列表])

{

//方法体

}

二、两种构造方法

1.不带参数的构造方法

举例:定以一个圆circle类

public class SameCircle
{
    public SameCircle1() //无参数的构造方法
    {
    }
}
2.有参数的构造方法
举例:同样定义一个圆
ublic class SameCircle
{
    public SameCircle2( int noX, int noY, int nRa) //参数的构造方法,定义了圆心,半径
    {
    }
}
************************************
    构造方法通过new调用 例如 创建对象时

Student stu = new Student(); new 后面跟构造方法名完全一样
******************************************************************
//总结:
//(1)构造方法的名字和类的名字要相同,大小写字母也要一样。
//(2)构造方法不能有返回值类型。
//(3)在构造方法体中也不能用return返回一个值。
//(4)主要作用是用于对象的初始化
//(5)在创建对象时系统自动调用,不能再代码中显示的调用
//(6)一个类中可以定义多个构造方法(参数序列要有明显的区别,这样才好区分具体用哪个)
//(7)类中不定义构造方法时,系统会自动为该类生成一个没有参数的构造方法。
//父类
class Phone {
    //构造方法
    constructor(brand, price) {
        this.brand = brand;
        this.price = price;
    }
    //父类的成员属性
    call() {
        console.log("我可以打电话!");
    }
}

//子类继承父类
class SmartPhone extends Phone {
    //构造方法
    constructor(brand, price, color, size) {
        super(brand, price); // 相当于ed5的Phone.call(this, brand, price)
        this.color = color;
        this.size = size;
    }

    photo() {
        console.log("拍照");
    }
    playGame() {
        console.log("玩游戏");
    }
    //子类对父类方法的重写   子类不能直接调用父类的重名方法的 
    call() {
        console.log("我还可以视频通话!!");
    }
}

const xiaom = new SmartPhone('小米', 799, '黑色', '4.7inch');
console.log(xiaom);
console.log(xiaom.size);
xiaom.call(); //打印“我还可以视频通话!!”,而不是“我可以打电话!”
xiaom.photo();
xiaom.playGame();
// 重写:
子类对父类的函数进行重新定义,即在子类中定义某方法与其父类具有相同的名称和参数.
2.18 class类中getter和setter设置
// get和set
class Phone {
    //对对象的动态属性进行封装
    get price() {
        console.log("价格属性被读取了");
        return 'i love you';
    }
    
    //可对设置的值进行判断
    set price(newVal) {
        console.log('价格属性被修改了');
    }
}
//实例化对象
let s = new Phone();
        
console.log(s.price);
console.log("\n");
s.price = 'free';
2.19 数值扩展

1、Number. EPSILON是JavaScript 表示的最小精度,EPSILON 属性的值接近于2. 2204460492503130808472633361816E-16 【2.22*10负16次方】

function equal(a, b) {
    if (Math.abs(a - b) < Number.EPSILON) {
        return true;
    } else {
        return false;
    }
}
console.log(0.1 + 0.2 === 0.3);
console.log(equal(0.1 + 0.2, 0.3))

2、二进制和八进制

let b = 0b1010; //二进制
console.log(b);
let o = 0o777; //八进制
console.log(o);
let d = 100; //十进制
console.log(d);
let x = 0xff; //十六进制
console.log(x);

3、 Number.isFinite 检测一个数值是否为有限数

console.log(Number.isFinite(100));
console.log(Number.isFinite(100 / 0));
console.log(Number.isFinite(Infinity)); //无穷

4.Number.isNaN检测一个数值是否为NaN

console.log(Number.isNaN(123));

5、Number.parseInt、Number . parseFloat字符串转整数

console.log(Number.parseInt('5211314love'));
console.log(Number.parseFloat('3.1415926神奇'));

6、 Number.isInteger判断一个 数是否为整数

console.log(Number.isInteger(5));
console.log(Number.isInteger(2.5));

7、Math.trunc 将数字的小数 部分抹掉

console.log(Math.trunc(3.5));

8、 Math.sign 判断一个数到底为正数、负数还是零

console.log(Math.sign(100));
console.log(Math.sign(0));
console.log(Math.sign(-20000));
2.20 ES6 对象方法扩展

1、Object.is 判断两个值是否完全相等

console.log(Object.is(120, 120)); //ture
console.log(Object.is(120, 121)); //flase
console.log(Object.is(NaN, NaN)); //ture
console.log(NaN === NaN); //flase,所以Object.is和===不一样  两个NaN 进行比较除了不等于都是false 

2、Object.assign 对象的合并

//用于配置合并
const config1 = {
    host: 'localhost ',
    port: 3306,
    name: 'root',
    pass: 'root',
    test: 'test'
};
const config2 = {
    host: 'http://atguigu.com',
    port: 33060,
    name: 'baidu.com',
    pass: 'iloveyou',
    //test2: 'test2' //有则覆盖,无则不覆盖
}  
console.log(Object.assign(config1, config2)); //2覆盖1

3、Object. setPrototype0f(设置原型对象)、Object.getPrototypeof(获取原型对象)

const school = {
    name: '尚硅谷'
}
const cities = {
    xiaoqu: ['北京', ' 上海', '深圳']
}

Object.setPrototypeOf(school, cities); //将cities设置为school的原型对象,但最好不用此方法设置
console.log(school);
console.log(Object.getPrototypeOf(school)); //获取school的原型对象
2.21 模块化

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

优势与规范化产品
1、模块化的优势有以下几点:

1)防止命名冲突2)代码复用3)高维护性

2、ES6之前的模块化规范有:

1)CommonJS => NodeJS、Browserify2)AMD => requireJS3)CMD => seaJS

浏览器使用ES6模块化引入模块

ES6 模块化语法

模块功能主要由两个命令构成:export 和import。1、export命令用于规定模块的对外接口2、import命令用于输入其他模块提供的功能

//import 导入模块变量-----这里在导入的时候变量需要重命名,import的时候必须使用大括号!
//按需引入math模块各个变量
import{del,add,sub as subList}from"@/api/math.js"
console.log(de1)
console.log(add(2,4))
console.log(subList(20,3))
//一次性全部导入模块变量!用*
//全部引入math.js模块变量
import*as math from"@/api/math.js"  // *——代表所有  math——自定义的重命名
console.1og(math.de1)
console.1og(math.add(2,4))
console.Log(math.subList(20,3)
2.22 ES6模块暴露数据语法汇总
//分别暴露
在每个需要暴露的数据的前面加 export 
//统一暴露
let school = '尚硅谷';
function find() {
    console.log("我们可以帮助你找工作");
}
export{school,find};
//默认暴露
export default {
    school: 'ATGUIGU',
    change: function () {  //m3.default.change();
        console.log("我们可以改变你!!");
    }
}

2.23 ES6模块引入模块数据语法汇总

//1.通用导入方式
import*as math from"@/api/math.js"  // *——代表所有  math——自定义的重命名
//2. 解构赋值形式
//import {school, teach} from"./m1.js";
//import {school as guigu, find} from "./m2.js";
// 默认暴露的形式
//import {default as m3} from "./m3.js";

//3. 简便形式,只针对默认暴露
import m3 from "./m3.js";
console.log(m3);
浏览器使用ES6模块化方式二
//html文件里面的script标签
<script src="./app.js" type="module"></script>         // 注意类型需要设置为module 
2.24 Babel 对ES6模块化代码转化

Babel 是一个javaScript编译器,可以将es6比较新的语法转化为浏览器可以识别的语法

需要安装的工具
babel-cil   babel-preset-env   browserify (browserify进行打包比较简单)  在项目中一般使用webpack 进行打包
npm init --yes 进行初识化
-D 开发依赖
1.安装工具babel-cil   babel-preset-env   browserify -D 表示开发依赖
2.之后需要使用 npx babel src/js -d dist/js  进行转换
3. 打包 npx browserify dist/js/app.js -o  (-o 表示输出 表示最终把文件输出到那个位置)
2.25 ES6模块化引入NPM包
npm i jquery 
// 修改背景颜色为粉色
import $ from 'jquery';   es6 导入npm 包的语法   // 相当于 const $ =require("jquery");
$('body').css('background','pink');

3.ES7新特性


3.1.Array.prototype.includes Includes

方法用来检测数组中是否包含某个元素,返回布尔类型值

3.2.指数操作符

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

Math.pow(2,10);  // 1024  相当于2的10次方

4 ECMASript 8 新特性


4.1.async 和 await

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

4.1.1.async 函数

async 函数的返回值为 promise 对象, // promise 对象代表未来将要发生的事件,用来传递异步操作的消息

promise 对象的结果由 async 函数执行的返回值决定

4.1.2.await 表达式
  1. await 必须写在 async 函数中

  1. await 右侧的表达式一般为 promise 对象

  1. await 返回的是 promise 成功的值

  1. await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处.await 表达式

4.2 Object.values 和 Object.entries
  1. Object.values()方法返回一个给定对象的所有可枚举属性值的数组

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

4.3.Object.getOwnPropertyDescriptors

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

console.log(Object.getOwnPropertyDescriptors(school));

5.ES9新特性


5.1.Rest/Spread 属性

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

function connect({host, port, ...user}) { // host 和port 还是存储到变量里面,其余其他属性键或值存储到user 里面

 console.log(host);                          // 如果有更多的参数,参数也会存储到user当中去  【user 只是随意的命名】
 console.log(port);
 console.log(user);
}
connect({
 host: '127.0.0.1',
 port: 3306,
 username: 'root',
 password: 'root',
 type: 'master'
});
5.2.正则表达式命名捕获组

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

let str = '<a href="http://www.atguigu.com">尚硅谷</a>';
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result = reg.exec(str);
console.log(result.groups.url);
console.log(result.groups.text);

eg:进行对象的合并

正则扩展——命名捕获分组

对分组匹配的结果进行命名方便对结果进行处理 【对捕获结果添加属性,方便我们进行提取】

通过正则 对字符串的部分信息进行捕获提取

5.3.正则表达式反向断言

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

//声明字符串
let str = 'JS5211314 你知道么 555 啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);   // 555  根据啦的内容判断前面的内容
//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str)   // 根据么判断后面的 5 
根据目标内容的前面和后面对它做唯一性的识别
5.4 ES9 正则扩展——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)

6.ES10


6.1.Object.fromEntries

用来创建对象,接收二维数组或者Map

map 是一种数据结构,其实也是一种对象

6.2.trimStart 和 trimEnd

字符串的扩展方法

trim 清除字符创两侧的空白字符
trimStart   trimEnd  用来指定清除左侧还是右侧的空白字符
6.3.Array.prototype.flat 与 flatMap

flat : 平 将多维数组转换为低维数组

二维转一维

三维转一维

6.4.Symbol.prototype.description
用来获取 Symbol 的字符串描述

7 . ECMASript 11 新特性


7.1类的私有属性

对属性的一个封装,不让外部对他们做直接的操作

通过构造方法来进行初始化 私有属性声明的时候需要用到 #

7.2.Promise.allSettled
Promise.all()    全部成功之后才可以返回一个成功的结果           想要最终的成功的结果的时候使用
Promise.allSettled()   始终可以返回一个成功,始终能够得到每一个promise 成功和失败的状态以及结果  想要得到每一个的结果的时候使用
7.3.String.prototype.matchAll

字符串扩展 matchAll 方法用来得到正则批量匹配的结果

返回的是一个可迭代对象

也可以用扩展运算符将它展开

7.4.可选链操作符

?.当我们面对对象类型的参数的时候

允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。
7.5.动态 import 导入
ES6 模块化是一个静态的模块系统 在写import的时候一般是在app.js 入口文件中写入之后进行导入工作的
动态import 可以实现按需要加载

原来的导入是一口气将所有将会用到的外部文件import

ES11 支持import函数 返回的是Promise对象 在要使用到外部文件的时候在引入 实现了懒加载

Promise成功的值就是导入的对象

7.6 BigInt类型 【大整数型】

在普通整型数据的基础上面加 n 就可以啦

应用于大数值的运算

BigInt 类型不能直接和普通int 类型进行运算

7.7.globalThis 对象
含义:全局的this    无论执行环境是什么,始终指向全局对象
对全局对象进行操作可以使用,这样子可以忽略环境直接使用

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值