ES6-ES11


0.绪

浏览器:javascript 三个部分: ECMAScript + BOM + DOM
服务器:javascript = ECMAScript + 系统内置的核心模块(fs http)

ECMAScript 是什么?
它是一个 规范。 ECMA 是一个组织协会,协会专门负责制定各种规则。他们制定了一个 ECMAscript 规范,规定脚本语言实现。
有哪些语言实现这个规范: 1. JavaScript 2. actionScript(flash 动画 flash小游戏)

发展过程中 js 有很多的版本的迭代,以ES5为基础,其中ES6拓展了许多新的语法,较为重要。

es6—>es5 在线网站(babel 翻译器)

https://www.babeljs.cn/repl

1.ECMAScript 6

1.1 let 和 const

1.1.1 let 关键字

使用var关键字声明变量的弊端:

1、var声明的变量有预解析,造成 逻辑混乱,可以先使用,后声明

2、var可以重复定义同一个变量,逻辑错误,第二次应该是修改变量,而不是定义

3、var用在for循环条件中,造成for 循环的污染的问题

4、var 声明的变量没有块级作用域(ES5中的作用域:全局和局部)

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

  1. 不允许重复声明
  2. 块儿级作用域
  3. 不存在变量提升
  4. 不影响作用域链

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

<div class="item" style="width: 50px;height: 50px;background-color: red"></div>
<div class="item" style="width: 50px;height: 50px;background-color: red"></div>
<div class="item" style="width: 50px;height: 50px;background-color: red"></div>

<script>
    let items=document.getElementsByClassName("item");
    for (var i=0;i<items.length;i++){
        items[i].onclick=function (){
            items[i].style.backgroundColor='pink';
        }
    }
    console.log(windows.i)  //3 

    // 相当于
    {
        var i = 0;
        items[i].onclick=function (){
            items[i].style.backgroundColor='pink';
        }
        ...
        // 最后为每个div添加的点击事件的触发对象都是items[i],这个i就是window.i:3
        // 如果用let 就有块级作用域,就不会出现这种情况
    }
</script>

1.1.2 const 关键字

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

  1. 声明必须赋初始值
  2. 标识符一般为大写
  3. 不允许重复声明
  4. 值不允许修改
  5. 块儿级作用域
const team = ['uzi','MXLG','Ming','Letme'];
team.push('Meiko'); //不报错,常量地址没有发生变化

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

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

1.2 解构赋值

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

数组解构

const arr = ['张学友', '刘德华', '黎明', '郭富城'];
//数组的解构赋值,按顺序取值
//完全结构
let [zhang, liu, li, guo] = arr;

// 部分解构
let [z] = arr;
console.log(z);  //张学友
// 不按顺序
let [ , ,l] = arr;
console.log(l);  //黎明

对象解构

//对象的解构赋值,按key取值
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;

//解构之后重命名
const obj = {name: "Liwker", age: 21};
let {name:myName} = obj;    // 解构之后重命名为myName

字符串解构

// 和数组解构类似
let string = "xyz";

let [a,b,c] = string;
console.log(a);  //x
console.log(b);  //y
console.log(c);  //z

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

1.3 模板字符串

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

  1. 字符串中可以出现换行符
  2. 可以使用 ${xxx} 形式输出变量
// 定义字符串
let str = 
    `<ul>
        <li>沈腾</li>
        <li>玛丽</li>
        <li>魏翔</li>
        <li>艾伦</li>
    </ul>`;

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

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

1.4 简化对象写法

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

let name = "Liwker";
function hello(){
  console.log("Hello~");
}

const obj = {
  // 简化版,当属性名和变量名一样时
  name,
  hello,
  // 方法名也是一样
  fn,
  // 常规定义方法
  hi: function(){
    console.log("Hi~");
  },
  // 简化定义方法
  say(){
    console.log(this.name);
  }
}

obj.hello();
obj.say();

1.5 箭头函数

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

箭头函数的注意点:

  1. 如果形参只有一个,则小括号可以省略
  2. 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
  3. 箭头函数this是静态的,指向声明时所在作用域下this 的值,就连call()都不能改变
  4. 箭头函数不能作为构造函数实例化
  5. 不能使用arguments
// 无参数 无返回
let func11 = () => console.log('func11');
func11();

// 无参数 有返回
let func22 = () => 'func22';
console.log(func22());

// 有参数 无返回
let func33 = x => console.log('func33', x);
func33(2);

// 有参数 有返回
let func44 = (x, y) => {
    let sum = x + y; 
    return sum + 'func44';
};
console.log(func44(1, 2));

// 如果return的是单一个对象,则需要加上大括号和return
// let func55 = x => {a:10, b:20};    //报错
let func66 = x => {
    return {a:10, b:20}
};

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

//需求-1  点击 div 2s 后颜色变成『粉色』
ad.addEventListener("click", function(){
    //定时器
    setTimeout(() => {
        //修改背景颜色 this
        this.style.background = 'pink';
    }, 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 有关的回调:事件回调, 对象的方法

1.6 函数形参默认值

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

  1. 可以给形参赋初始值,一般位置要靠后
  2. 与解构赋值结合
function A({host='127.0.0.1',username,password,port}){
    console.log(host+username+password+port);
}

A({
    username:'Liwker',
    password:'123456',
    port:3306
});

//防止不传实参时候的报错
function func2({name, age} = {}){
    console.log(name, age);
}
func2();   //undefined undefined

//指定默认值
function func2({name="Liwker", age=21} = {}){    
    console.log(name, age);
}
func2();  //Liwker 21

1.7 rest参数

ES6引入rest参数,用于获取函数的实参,用来代替arguments
位置是在函数声明的形参列表里
function fun(args){}

函数的属性 arguments 是实参列表,是一个伪数组,本质是一个对象
而rest参数是一个真数组,可以调用高级函数方法

// rest 参数必须是最后一个形参
function fun(a, b, ...args){  // 把剩余的参数都交给 args
    console.log(a);
    console.log(b);
    console.log(args);    //[3,4,5]
}
fun(1,2,3,4,5)

1.8 spread扩展运算符

扩展运算符是能将数组转换为逗号分隔的参数序列,可以理解为 展开
和rest参数类似,但位置不同,扩展运算符是在 函数调用的实参列表里
fun(test);

const test=['AA','BB','CC']
function fun(){
    console.log(arguments);
}
fun(...test);  //0:'AA' 1:'BB' 2:'CC'

应用:

  1. 数组、对象的合并

    const A = ["a", "b"];
    const B = ["c", "d"];
    const C = [...A, ...B];    // 相当于 ["a","b", "c","d"]
    console.log(C)   //[aa,bb,cc,dd]
    
    const O1 = {a:1, b:2};
    const O2 = {c:3};
    const O3 = {...O1, ...O2};
    console.log(O3)   //{a: 1, b: 2, c: 3}
  2. 数组的克隆

    const A = ['a','b','c'];
    const B = [...A];    // 相当于 ["a","b","c"]
    console.log(B)   //[a,b,c]

    注意:如果A里有引用类型,如对象,数组,那么B里也是浅拷贝的

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

    const A = documents.querySelectorAll('div');
    const B = [...A];
    console.log(B) // [div,div,div]
    // 同样对 arguments 这样的伪数组也能转换

1.9 Symbol

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

Symbol特点:

  • Symbol的值是唯一的,用来解决命名冲突的问题
  • Symbol值不能与其他数据进行运算
  • Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
  1. 创建

    let s = Symbol('aa');
    let s2= Symbol('aa');
    console.log(s===s2)   // false
    
    // Symbol.for()方法创建
    let s3 = Symbol.for('bb');
    let s4 = Symbol.for('bb');
    comsole.log(s3===s4) // true
  2. 不能与其他数据进行运算

    s + 100  //error
    s > 100  //error
    s + s  //error
    `your symbol is ${s}` // TypeError: can't convert symbol to string

Symbol内置值

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

详细请查看 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol

推荐阅读 https://es6.ruanyifeng.com/#docs/symbol

1.10 迭代器

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

ES6创造了一种新的遍历命令for…of循环

原理:

  1. 创建一个指针对象,指向数据结构的起始位置
  2. 第一次调用==next()==方法,指针自动指向数据结构第一个成员
  3. 接下来不断调用next(),指针一直往后移动,直到指向最后一个成员
  4. 每调用next()返回一个包含value和done属性的对象
const xiyou=['AA','BB','CC','DD'];
// for(let v of xiyou){
//     console.log(v) 
// 'AA','BB','CC','DD'
// for in保存的是键名,for of保存的是键值
// }
let iterator = xiyou[Symbol.iterator]();
console.log(iterator.next()); //{{value:'唐僧',done:false}}
console.log(iterator.next()); //{{value:'孙悟空',done:false}}

给对象自定义

const banji = {
    name : "自定义",
    stus: [
        'aa',
        'bb',
        'cc',
        'dd'
    ],
    // 添加迭代接口,for of本质就是调用Symbol.iterator()方法
    [Symbol.iterator](){
        let index = 0;
        let _this = this;
        return {
            next: () => {
                if(index < this.stus.length){
                    const result = {value: _this.stus[index],done: false};
                    //下标自增
                    index++;
                    //返回结果
                    return result;
                }else {
                    return {value: underfined,done:true};
                }
            }
        }
    }
}


for(let v of banji){
    console.log(v);  // aa bb cc dd
}

1.11 生成器

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

function * gen (){    //函数名和function中间有一个 * 
    // 这里是第一段
    yield '耳朵';     //yield是函数代码的分隔符
    // 这里是第二段
    yield '尾巴';
    // 这里是第三段
    yield '真奇怪';
    // 这里是第四段
}
let iterator = gen();  // 执行接收返回对象
console.log(iteretor.next());   // {value:'耳朵',done:false}
// next()执行第一段,并且返回yield后面的值
console.log(iteretor.next()); // {value:'尾巴',done:false}
console.log(iteretor.next()); // {value:'真奇怪',done:false}
console.log(iteretor.next()); // {value:'undefinde',done:true}

代码说明:

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

实例1:生成器函数的参数传递

function * gen(args){
    console.log(args);
    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());
console.log(iterator.next('BBB'));  //next中传入的BBB将作为yield 111的返回结果
console.log(iterator.next('CCC'));  //next中传入的CCC将作为yield 222的返回结果
console.log(iterator.next('DDD'));  //next中传入的DDD将作为yield 333的返回结果

实例2:用生成器函数的方式解决回调地狱问题

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();

实例3:模拟异步获取数据

function one(){
    setTimeout(()=>{
        let data='用户数据';
        iterator.next(data)
    },1000)
}
function two(){
    setTimeout(()=>{
        let data='订单数据';
        iterator.next(data)
    },2000)
}
function three(){
    setTimeout(()=>{
        let data='商品数据';
        iterator.next(data)
    },3000)
}

function * gen(){
    let users=yield one();
    console.log(users)
    let orders=yield two();
    console.log(orders)
    let goods=yield three();
    console.log(goods)
}

let iterator = gen();
iterator.next();

1.12 Promise

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

1.基本特征

const p =new Promise((resolve, reject)=>{
    setTimeout(()=>{
        let data='数据库数据'
        // resolve(data);
        reject(data);
    })
})

p.then(function (value){         //成功则执行第一个回调函数,失败则执行第二个
    console.log(value)
},function (reason){
    console.error(reason)
})

2.Promise.then()方法

const p =new Promise((resolve, reject) =>{
    setTimeout(()=>{
        resolve('用户数据');
    })
});

//then()函数返回的实际也是一个Promise对象
//1.当回调后,返回的是非Promise类型的属性时,状态为fulfilled,then()函数的返回值为对象的成功值,如reutnr 123,返回的Promise对象值为123,如果没有返回值,是undefined

//2.当回调后,返回的是Promise类型的对象时,then()函数的返回值为这个Promise对象的状态值

//3.当回调后,如果抛出的异常,则then()函数的返回值状态也是rejected
let result = p.then(value => {
    console.log(value)
    // return 123;
    // return new Promise((resolve, reject) => {
    //     resolve('ok')
    // })
    throw 123
},reason => {
    console.log(reason)
})
console.log(result);

3.Promise.catch()方法

//catch()函数只有一个回调函数,意味着如果Promise对象状态为失败就会调用catch()方法并且调用回调函数

const p = new Promise((resolve, reject) => {
    setTimeout(()=>{
        reject('出错啦')
    },1000)
})

p.catch(reason => {
    console.log(reason)
})

应用:发送AJAX请求

//ajax请求返回一个promise
function sendAjax(url){
    return new Promise((resolve, reject) => {

        //创建对象
        const x =new XMLHttpRequest();

        //初始化
        x.open('GET',url);

        //发送
        x.send();

        //时间绑定
        x.onreadystatechange = ()=>{
            if(x.readyState === 4 ){
                if(x.status >= 200 && x.status < 300){
                    //成功
                    resolve(x.response)
                }else {
                    //失败
                    reject(x.status)
                }
            }
        }
    })
}

//测试
sendAjax("https://api.apiopen.top/getJoke").then(value => {
    console.log(value)
},reason => {
    console.log(reason)
})

1.13 集合

1.13.1 Set

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

  1. size 返回集合的元素个数
  2. add() 增加一个新元素,返回当前集合
  3. delete() 删除元素,返回boolean值has检测集合中是否包含某个元素,返回boolean值
  4. has() 检测Map中是否包含某个元素,返回boolean值
  5. clear() 清空集合,返回undefined

特性

let s = new Set();
let s2 = new Set(['A','B','C','D'])

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

//添加新的元素
s2.add('E');

//删除元素
s2.delete('A')

//检测
console.log(s2.has('C'));

//清空
s2.clear()

console.log(s2);

应用

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 result2 = [...new Set(arr)].filter(item => new Set(arr2).has(item))
console.log(result2);

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

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

1.13.2 Map

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

  1. size 返回Map的元素个数
  2. set() 增加一个新元素,返回当前Map
  3. get() 返回键名对象的键值
  4. has() 检测Map中是否包含某个元素,返回boolean值
  5. clear() 清空集合,返回undefined
let m = new Map();
m.set('name','ran');
m.set('change',()=>{
    console.log('改变!')
})
let key={
    school:'atguigu'
}
m.set(key,['成都','西安']);

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

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

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

// //清空
// m.clear()

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

1.14 Class 面对对象

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

继承:一般使用 extends关键字 和 super()方法 来进行继承,但是在es5里面,也是没有extends继承,而是使用的prototype原型继承完成的。

// 基本语法
class shouji {
    // 构造函数
    constructor(brand,price) {
        // 数据成员
        this.brand=brand;
        this.price=price
    }
    // 成员函数
    call(){
        console.log('我可以打电话')
    }
}

let A = new shouji('1+',3999);
console.log(A)

静态成员

class Person{
    // 静态成员,是属于类的,实例对象不能直接访问和修改
    static name = "手机";
}
let nokia = new Person();
console.log(nokia.name); // undefined
console.log(nokia.constructor.name); // "手机"

es5 构造函数继承

// 用函数定义父类
function Phone(brand,price){
    this.brand=brand;
    this.price=price;
}
// 给类的实例定义方法
Phone.prototype.call=function (){
    console.log("我可以打电话");
}
// 给类定义静态方法
Phone.fly = function(){
    console.log('想什么呢,手机是不会飞的~');
}

// 定义子类
function SmartPhone(brand,price,color,size){
    // 子类继承父类的属性,需要将 this 指向父类中的 属性
    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('我可以玩游戏');
}

// 实例对象
const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch')
console.log(chuizi);
// 调用对象的方法
chuizi.call();
// 调用类的静态方法
Phone.fly();

Class的类继承

class Phone{
    constructor(brand,price) {
        this.brand=brand;
        this.price=price;
    }
    //父类的成员属性
    call(){
        console.log('我可以打电话');
    }

    //定义静态方法
    static fly(){
        console.log('想什么呢,手机是不会飞的~');
    }
}
class SmartPhone extends Phone{
    constructor(brand,price,color,size) {
        //注意:在ES6中使用继承时,constructor中必须调用super()方法,其本质是在调用父类的constructor方法。通过这样的方式来达到属性继承的效果
        super(brand,price);
        this.color=color;
        this.size=size;
    }

    photo(){
        console.log('拍照');
    }

    playGame(){
        console.log('打游戏');
    }

    // 重写父类函数
    call(){
        console.log('我不仅可以打电话,还可以AI通话');
    }
}
const xiaomi=new SmartPhone('小米',1999,'黑色','4.7inch')
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
Phone.fly();

get和set设置

class Phone{
    get price(){
        console.log("价格被读取了")
        return 'I LOVE YOU'
    }

    set price(val){
        console.log('价格被修改了')
        return val;
    }
}

//实例化对象
let s = new Phone();
s.price=12  
// console.log(s.price)   //其实是调用price方法

1.15 数值扩展

// Number.EPSILON是 JavaScript的最小精度,属性的值接近于 2.22044...E-16
function equal(a,b){
    if(Math.abs(a-b) < Number.EPSILON){
        return true;
    }else {
        return false;
    }
}

console.log(equal(0.1 + 0.2 === 0.3))  //false
console.log(equal(0.1+0.2,0.3))  //true

//二进制和八进制
let b = 0b1010; //2进制
let o = 0o777;  //8进制
let d = 100;    //10进制
let x = 0xff;   //16进制
console.log(x)   //255

//检测一个数是否为有限数
console.log(Number.isFinite(100));  //true
console.log(Number.isFinite(100/0));  //false
console.log(Number.isFinite(Infinity));  //false

//检测一个数值是否为NaN
console.log(Number.isNaN(123))  //false

//字符串转整数
console.log(Number.parseInt('5213123love')); //5213123
console.log(Number.parseFloat('5.123123神器')); //5.123123

//判断是否为整数
console.log(Number.isInteger(5));  //true
console.log(Number.isInteger(2.5)); //false

//将小数部分抹除
console.log(Math.trunc(3.45345345345)) //3

//检测一个数到底是正数、负数、还是0
console.log(Math.sign(100)) //1
console.log(Math.sign(0))  //0
console.log(Math.sign(-123)) //-1

1.16 对象方法扩展

ES6新增了一些Object对象的方法:

  1. Object.is() 比较两个值是否严格相等,与『===』行为基本一致(+0与NaN)
  2. Object.assign() 对象的合并,将源对象的所有可枚举属性,复制到目标对象
  3. __proto__、setPrototypeOf、setPrototypeOf可以直接设置对象的原型
//1.Object.is 判断两个值是否完全相等
console.log(Object.is(120,120))  //true
console.log(Object.is(NaN,NaN))  //false

//2.Object.assign 对象的合并
const a = {
    name:'ran',
    age:12
}
const b = {
    pass:'i love you'
}
console.log(Object.assign(a,b))   //{name:'ran',age:'12',pass:'i love you'}

//3.Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
    name:'尚硅谷'
}
const cities = {
    xiaoqu:['北京','上海']
}
Object.setPrototypeOf(school,cities)
console.log(Object.getPrototypeOf(school))  //{xiaoqu: Array(2)}
console.log(school)  //{name: "尚硅谷"}

1.17 模块化

1.17.1 基本介绍

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

模块化的优势有以下几点:

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

模块化规范产品,ES6之前的模块化规范有:

  1. CommonJS ====> NodeJS、Browserify
  2. AMD ====> requireJS(较老)
  3. CMD ====> seaJS(较老)

语法

模块功能主要有两个命令构成:exportimport

  • export 命令用于规定模块的对外接口
  • import 命令用于输入其他模块提供的功能
export let school = '尚硅谷';
export function teach(){
    console.log('教技能')
}
import * as m1 from "./src/js/m1.js";
console.log(m1);

1.17.2 暴露语法汇总

1.统一暴露

//统一暴露
let school = '尚硅谷';
function findjob(){
    console.log('找工作吧');
}
//export {school,findjob}

2.默认暴露

//默认暴露
export default {
    school:'ATGUIGU',
    change:function(){
        console.log('我们可以改变你')
    }
}

1.17.3 引入语法汇总

1.通用导入方式

import * as m1 from "./src/js/m1.js"
import * as m2 from "./src/js/m2.js"
import * as m3 from "./src/js/m3.js"

2.解构赋值方式

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"

1.17.4 模块化方式2

<script src="./src//js/app.js" type=modeule></script>

2.ES7

  1. Array.prototype.includes:用来检测数组中是否包含某个元素,返回布尔类型值
  2. 在ES7中引入指数操作符**,用来实现幂运算,功能与Math.pow结果相同
//includes
const mingzhu = ['西游记','红楼梦','水浒传','三国演义']
console.log(mingzhu.includes('西游记'))  //true
console.log(mingzhu.includes('聊斋志异'))  //false

//**
console.log(2**10) // 1024

3. ES8

3.1 async函数

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

async函数:

  • async函数的返回值为promise对象
  • async返回的promise对象的结果值由async函数执行的返回值决定
async function fn(){
   //1.如果返回的是一个非Promise的对象,则fn()返回的结果就是成功状态的Promise对象,值为返回值
   //2.如果返回的是一个Promise对象,则fn()返回的结果与内部Promise对象的结果一致
   //3.如果返回的是抛出错误,则fn()返回的就是失败状态的Promise对象
   return new Promise((resolve,reject)=>{
       resolve('成功的数据');
   });
}
const result = fn();
result.then(value=>{
   console.log(value)  //成功的数据
},reason=>{
   console.log(reason)
})

3.2 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 res = await p;
        console.log(res);
    } catch (e) {
        console.log(e);
    }
}

//调用函数
main()  //失败了

应用:发送AJAX请求

//ajax请求返回一个promise
function sendAjax(url){
    return new Promise((resolve, reject) => {

        //创建对象
        const x =new XMLHttpRequest();

        //初始化
        x.open('GET',url);

        //发送
        x.send();

        //时间绑定
        x.onreadystatechange = ()=>{
            if(x.readyState === 4 ){
                if(x.status >= 200 && x.status < 300){
                    //成功
                    resolve(x.response)
                }else {
                    //失败
                    reject(x.status)
                }
            }
        }
    })
}

//async 与 await 测试
async function main(){
    let result = await sendAjax("https://api.apiopen.top/getJoke")
    console.log(result);
}
main();

3.3 ES8对象方法扩展

const school = {
    name:'尚硅谷',
    cities:['北京','上海','深圳'],
    xueke:['前端','Java','大数据','运维']
};

//获取对象所有的键
console.log(Object.keys(school));

//获取对象所有的值
console.log(Object.values(school));

//entries,用来创建map
console.log(Object.entries(school));
console.log(new Map(Object.entries(school)))

//对象属性的描述对象
console.log(Object.getOwnPropertyDescriptor(school))

const obj = Object.create(null,{
    name:{
        value:'尚硅谷',
        //属性特性
        writable:true,
        configurable:true,
        enumerable:true,
    }
})

4. ES9

4.1 运算扩展符与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'
})  //127.0.0.1  3306  {username: "root", password: "root", type: "master"}
const AA={
    username:'ran'
}
const BB={
    password:'lyyrhf'
}
const CC={
    job:'Java'
}
const D={...AA,...BB,...CC};
console.log(D) //{username: "ran", password: "lyyrhf", job: "Java"}

5. ES10

5.1 对象扩展方法

//二维数组
const res = Object.fromEntries([
    ['name','冉海锋'],
    ['cities','成都','武汉']
])
console.log(res) //{name: "冉海锋", cities: "成都"}

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

5.2 字符串扩展方法

//trim
let str= ' asd  '
console.log(str) //asd
console.log(str.trimStart()) //asd  清空头空格
console.log(str.trimEnd()) //  asd  清空尾空格

5.3 flat与flatMap

const arr = [1,2,3,[4,5,6,[7,8,9]]]
//参数为深度,是一个数字
console.log(arr.flat(2)) //[1,2,3,4,5,6,7,8,9]

const arr2=[1,2,3,4]
const result = arr2.flatmap(item => [item * 10]);
//如果map的结果是一个多维数组可以进行flat 是两个操作的结合

5.4 Symbol的description

用来获取Symbol的字符串描述

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

5.5 私有属性

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('Liwker', 18, '45kg');
console.log(girl.#age) //error
            console.log(girl); //Person{name: "Liwker", #age: 18, #weight: "45kg"}
girl.intro(); //Liwker 18  45kg

5.6 Promise

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

const p2 = new Promise((resolve, reject) => {
    setTimeout(()=>{
        reject('出错了!')
    },1000)
})

//调用allsettled方法:返回的结果始终是一个成功的,并且异步任务的结果和状态都存在
const res = Promise.allSettled([p1,p2]);
console.log(res)

// Promise {<pending>}
//     __proto__: Promise
//     [[PromiseState]]: "fulfilled"
//     [[PromiseResult]]: Array(2)

//调用all方法:返回的结果是按照p1、p2的状态来的,如果都成功,则成功,如果一个失败,则失败,失败的结果是失败的Promise的结果
const result = Promise.all([p1,p2])
console.log(result)

5.7 可选链操作符

//相当于一个判断符,如果前面的有,就进入下一层级
function main(config){
    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.8 动态import

btn.onclick = function(){
    //使用之前并未引入,动态引入,返回的其实是一个Promise对象
    import('./hello.js').then(module=>{
        module.hello();
    })
}

5.9 BigInt类型

//大整型
let n = 521n;
console.log(n,typeof(n))  // 521n  n 

//函数
let n = 123;
console.log(BigInt(n)) // 123n  //不要使用浮点型,只能用int

//大数值运算
let max = Number.MAX_SAFE_INTEGER; // 9007199254740991
console.log(max +1) // 9007199254740992
console.log(max +2) // 9007199254740992 出问题了
// 大整数不能直接与整数运算,要先转换
console.log(BigInt(max)+BigInt(1)) 9007199254740992n
console.log(BigInt(max)+BigInt(2)) 9007199254740993n

5.10 绝对全局对象globalThis

console.log(globalThis) // 相当于window,在node中为global
//适用于复杂环境下直接操作window

文章作者: Liwker
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Liwker !
评论
 上一篇
Vue核心 Vue核心
1.1 Vue 简介1.1.1. 官网 https://cn.vuejs.org/ 1.1.2. 介绍与描述 动态构建用户界面的渐进式 JavaScript 框架 作者: 尤雨溪 1.1.3. Vue 的特点 遵循 MVVM 模式
2021-08-12
下一篇 
AJAX AJAX
一、简介1.1 AJAX简介 AJAX全称为Asynchronous Javascript And XML,即异步JS和XML 通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据 AJAX不是新的编程语言,而是一种将
2021-04-21
  目录