ES6语法笔记(ES6~ES11)

3 篇文章 0 订阅

相关代码和笔记已经同步到gitee,需要自取
链接地址:ES6学习笔记

1.let

        // let声明变量
        let a;
        let b,c,d;
        let e = 100;
        let f = 110,g = 'qwe',h = [];

1.1:let声明变量的特性

  • 1.不能重复声明变量
        //1.不能重复声明
        let star = '罗';
        let star = "小猪" //error
  • 2.let的块级作用域
 		//全局|函数|eval
        {
            let girl = '小红';
            // var没有块级作用域 可以读取到
        }
        console.log(girl);//error|Uncaught ReferenceError: girl is not defined
  • 3.不存在变量提升
    //var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
        console.log(song);//输出 undefined
        var song = '恋爱达人'

        console.log(song);//error
        let song = '恋爱达人'
  • 4.不影响作用域链

        // 4.不影响作用域链
        {
            let school = 'abc';
            function fn(){
                console.log(school);
                // 函数内部没有school变量,所以向上一级找school变量,let不影响作用域链效果
            }
            fn();//输出abc
        }

1.2:let实践案例

<!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>Document</title>
</head>

<body>
    <div>
        <h2>点击切换颜色</h2>
        <div class="item" style="margin: 10px;width: 50px;height: 50px;background-color: red"></div>
        <div class="item" style="margin: 10px;width: 50px;height: 50px;background-color: red"></div>
        <div class="item" style="margin: 10px;width: 50px;height: 50px;background-color: red"></div>
    </div>

    <script>
        //获取div的元素对象
        let items = document.getElementsByClassName('item');
        // 遍历并绑定事件
        for(var i = 0;i < items.length;i++){
            items[i].onclick = function() {
                //修改当前元素的背景颜色
                // this.style.background = 'pink';正常
                items[i].style.background = 'pink' //error
            }
        }
        console.log(i);//3
        // 报错原因:循环结束后i=3 点击事件触发时,数组下标越界
        // 解决:将var换成let  let具有块级作用域,互不影响
    </script>
</body>

</html>

2.const

  • 声明常量:const School = “学校”;

特性:

  • 一定要赋初始值
  • 一般常量尽量使用大写(潜规则)
  • 常量的值不能修改
  • 具有块级作用域
{
    const pyaler = 'uzi'
}
console.log(player) //error
  • 对于数组和对象的元素修改,不算作对常量的修改
const team = ['uzi','MXLG','Ming','Letme'];
team.push('Meiko'); //不报错,常量地址没有发生变化
team = 100 //报错

3.变量的解构赋值

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

  • 数组的解构:
        // 1.数组的解构
        const F4 = ['小沈阳', '刘能', '赵四', '宋小宝']
        let [xiao, liu, zhao, song] = F4;
        console.log(xiao)
        console.log(liu)
        console.log(zhao)
        console.log(song)
  • 对象的解构:
        // 2.对象的解构:
        const zhao = {
            name:'赵本山',
            age:'不详',
            xiaopin:function(){
                console.log("演小品");
            }
        };

        let {name,age,xiaopin} = zhao;
        console.log(name);
        console.log(age);
        console.log(xiaopin);
        xiaopin();

image-20220415103816265

4.模板字符串

ES6引入新的声明字符串的形式反引号 ``

  • 声明:
let str = `我也是一个字符串!`;
console.log(str,typeof str);//我也是一个字符串! string
  • 特性

1.内容中可以直接出现换行符

        let str = '<ul>
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                    </ul>'
        console.log(str);// 报错 以前的解决方案是字符串拼接
    //ES6可以模板字符串可以之间出现换行符
            let str = `<ul>
                <li>1</li>
                <li>2</li>
                <li>3</li>
                </ul>`
    console.log(str);//正确

2.变量拼接

let love = '刘亦菲';
let out = `${love}很漂亮!`;
console.log(out);//刘亦菲很漂亮!

5.简化对象写法

ES6允许再打括号里面直接写入变量和函数,作为对象的属性和方法:

        let name = '刘亦菲';
        let ins = function(){
            console.log('是美女');
        }

        const girl = {
            name,//等价于name:name
            ins,
            func(){//等价于function:func(){};
                console.log('ES6func');
            }
        }
        console.log(girl);

6.箭头函数

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

        // 声明一个函数

        // 原来
        // let fn = function(){};

        // ES6
        let fn = (a,b)=>{
            return a+b;
        }
        // 调用函数
        let result = fn(1,2);//3
        console.log(result);

特性:

  • 1.箭头函数this是静态的,this始终指向这个箭头函数所在作用域的外层作用域

    原来的this是指向调用者的,谁调用就指向谁

       function getName1() {
            console.log(this.name);
        }
        let getName2 = () => {
            console.log(this.name);
        }
        // 设置window对象的name属性
        window.name = '学习';
        const school = {
            name:"xuexi"
        }
        
        // 直接调用
        getName1();//学习 this指向window
        getName2();//学习 this指向window

        // call方法调用
        getName1.call(school);//xuexi this指向调用该方法的school对象
        getName2.call(school);//学习 
箭头函数的this指向 是看这个箭头函数所在作用域的外层作用域
比如:
var obj = {
x:100,
show(){
setTimeout( ( )=>{console.log(this.x) }, 500 )
}
}
这个例子中的箭头函数的外层上下文为show()这个方法,show()方法所在的上下文就是对象obj

再看例子:
var obj = {
a:5,
fun:()=>{
console.log(this);
}
}
这个例子中的箭头函数直接作为对象obj的方法,所以它的外层上下文就是obj,而obj是在window上下文中定义的,所以fun()中的this指向window
  • 2.不能作为构造实例化对象
//不能作为构造函数实例化对象
        let Person = (name,age)=>{
            this.name = name;
            this.age = age;
        }
        console.log(me);//报错:07.箭头函数.html:53 Uncaught TypeError: Person is not a constructor
  • 3.不能使用arguments变量
//不能使用arguments变量
        let fun = () => {
            console.log(arguments);
        }
        fun(1, 2, 3);//报错:arguments is not defined
  • 4.箭头函数的省略

    • 1.省略小括号,当形参有且只有一个的时候
            let add = n => {
                return n+n;
            }
            console.log(add(9));//18
    
    • 2.省略大括号,当代码体只有一条语句的时候,此时return必须省略,语句的执行结果就是函数的返回值
            let pow = n => n*n;
            console.log(pow(9));//81
    

箭头函数实践:

    <div id="ad" style="width: 200px;height: 200px;background: #58a;"></div>
    <script>
        // 箭头函数实践
        // 需求: 点击div  1s后变成粉色
        let ad = document.querySelector('#ad');
        console.log(ad);
        ad.addEventListener("click", function () {
            // 定时器
            setTimeout(function () {
                // 修改背景色 this
                console.log(this); //window
                this.style.background = 'pink';//定时器调用,this指向window
            }, 1000)
        })
        //点击报错
    </script>
*******************************************************************
        //以前的解决方法
        ad.addEventListener("click", function () {
            let _this = this;//保存调用方法的this
            // 定时器
            setTimeout(function () {
                // 修改背景色 this
                console.log(this); //window
                _this.style.background = 'pink';
            }, 1000)
        })
********************************************************************
        // 箭头函数解决:
        ad.addEventListener("click", function () {
            setTimeout(() => {
                console.log(this);//指向对象ad
                this.style.background = 'pink';
            }, 1000)
        })
        //箭头函数适合与this无关的回调 ,定时器,数组的对调
        // 箭头函数不适合与this有关的回调,事件回调,对象的方法
        let a = {
            name:"贵妇",
            getName:function(){
                this.name
                console.log(this);
            }
        }
        a.getName();//this指向a

        let b = {
            name:"贵妇b",
            getName:()=>{
                this.name
                console.log(this);
            }
        }
        b.getName();//this指向window

7.给函数参数赋初始值

  • 1.可以给形参赋初始值,一般位置要靠后(潜规则)
        // ES6允许给函数参数赋初始值
        // 1.形参初始值,具有默认值的参数,一般位置要靠后(潜规则)
        function add(a, b, c=10) {
            return a + b + c;
        }
        let result = add(1, 2);
        console.log(result);//10
  • 2.与解构赋值结合使用

      // 2.与解构赋值结合使用
      function connect({host='127.0.0.0',userName,password,port}){
          console.log(host);
          console.log(userName);
          console.log(password);
          console.log(port);           
      }
      // 调用
      connect({
          // host:'localhost',
          userName:'root',
          password:'root',
          port:3306
      })
    

8.rest参数

  • ES6引入rest参数,用于获取函数的实参,用来代替arguments
//ES5获取参数的形式
function date(){
	console.log(arguments);
}
date(1,2,3)//返回一个对象

//ES6  reset参数(剩余参数)
function date2(...args) {
   console.log(args);
}
date2(4,5,6)//返回一个数组  可以使用数组的api方法
        
// 注意rest参数必须放在参数最后
function date3(a,b,...args){
    console.log(a);
    console.log(b);
    console.log(args);//[3,4,5,6]
}
date3(1,2,3,4,5,6)

9.拓展运算符

  • […] 扩展运算符能将数组转换为逗号分隔的参数序列
        // 声明一个数组
        const num = [1,2,3];

        // 声明一个函数
        function total(){
            console.log(arguments);
        }

        total(num);//arguments对象里只有一个元素:[1,2,3]
        total(...num)//arguments对象里有三个元素:1,2,3 | 等价于total(1,2,3)

拓展运算符的运用:

  • 1.数组的合并
        // 1.数组的合并
        //ES5
        const hebing = shuzi.concat(zimu);
        console.log(hebing);//['1','2','3','a','b','c']
        //ES6 拓展运算符
        const hebing2 = [...shuzi,...zimu]
        console.log(hebing2);//['1','2','3','a','b','c']
  • 2.数组的克隆
        // 2.数组的克隆
        const a = ['q','w','e'];
        const b = [...a];//['q','w','e']  有引用数据类型注意是浅拷贝 没有完全复制
        console.log(b);
  • 3.将伪数组转化为真数组
// 3.伪数组转为真正的数组
        const divs = document.querySelectorAll('div');
        console.log(divs);//NodeList
        const divArr = [...divs];
        console.log(divArr);//[div, div, div]

10.Symbol的使用

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

1.Symbol特点:

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

1.创建

        // 创建Symbol
        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("很好");
        let s5 = Symbol.for("很好");
        console.log(s4, typeof s4);//Symbol(很好)    'symbol'
        console.log(s4 === s5);//true

2.Symbol注意:不能与其他数据进行运算

 // Symbol注意:不能与其他数据进行运算
        // let result = s + '100';//error
        // let result = s * 100;//error
        // let result = s + s;//error

ps:javaScript七种数据类型

//口诀:usonb
u:undefined
s:string symbol
o:object
n:null  number
b:boolean

2.Symbol创建对象属性:

向对象添加方法:up down

        let game = {
            name:"俄罗斯方块",
            up:"俄罗斯方块up",
            down:"俄罗斯方块down"
        };

        // 声明一个对象
        let methods = {
            up: Symbol(),
            down: Symbol()
        };
        game[methods.up] = function () {
            console.log("我可以改变形状");
        }
        game[methods.down] = function () {
            console.log("我可以快速下降");
        }
        console.log(game);

在这里插入图片描述

        let youxi = {
            name:"狼人杀",
            [Symbol('say')]:function(){
                console.log("我可以发言");
            },
            [Symbol('zibao')]:function(){
                console.log("我可以自爆");
            },
        }
        console.log(youxi);

在这里插入图片描述

3.Symbol内置属性:

详见: Symbol - 《阮一峰 ECMAScript 6 (ES6) 标准入门教程 第三版》 - 书栈网 · BookStack

class Person {
    static [Symbol.hasInstance](param){
        console.log(param);
        console.log("我被用来检测了");
        return false;
    }
}
let o = {};
console.log(o instanceof Person); //我被用来检测了,false

11.迭代器

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

  1. ES6创造了一种新的遍历命令for…of 循环,lterator接口主要供 for…of消费2)
  2. 原生具备iterator接口的数据(可用for of遍历)
  • Array
  • Arguments
  • Set
  • Map
  • string
  • TypedArray
  • NodeList

3.工作原理:

  • 创建一个指针对象,指向数据结构的起始位置
  • 第一次调用next()方法,指针自动指向数据结构第一个成员,接下来不断调用next(),指针一直往后移动,直到指向最后一个成员
  • 每调用next()返回一个包含value和done属性的对象
  • 注意:需要自定义遍历数据的时候,要想到迭代器
        // 声明一个数组
        const xiyouji = ['唐僧','孙悟空','猪八戒','沙僧'];
        // 使用for...in 遍历数组
        for (let v of xiyouji) {
            console.log(v);//v是键
        }
        // 使用for...of 遍历数组
        for (let v of xiyouji) {
            console.log(v);//v是值
        }

image-20220415160646756

image-20220415160505200

        let iterator = xiyouji[Symbol.iterator]();
        console.log(iterator);
        // 调用对象的next方法
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());

在这里插入图片描述

迭代器的应用:自定义遍历数据

const banji = {
    name : "终极一班",
    stus: [
        'xiaohong',
        'xiaoming',
        'xiaolan',
        'xiaobai'
    ],
    [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);  // xiaohong xiaoming xiaolan xiaobai
}

12.生成器

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

        // 生成器其实就是一个特殊的的函数 函数名和function中间有一个 * 
        function * gen(){
            console.log("hellow generator");
        }

        let iterator = gen();
        console.log(iterator);//不执行
        iterator.next();//打印hellow generator

在这里插入图片描述

image-20220415164406406

        // yield 相当于导函数代码的分隔符
        function * gen(){
            console.log("第一段");
            yield '一只没有耳朵';
            console.log("第二段");
            yield '一只没有尾巴';
            console.log("第三段");
            yield '真奇怪';
            console.log("第四段");
        }

        let iterator = gen();
        iterator.next();//执行第一段代码块
        iterator.next();//执行第二段代码块
        iterator.next();//执行第三段代码块
        iterator.next();//执行第四段代码块

image-20220415165041606

        function * gen(){
            console.log("第一段");
            yield '一只没有耳朵';
            console.log("第二段");
            yield '一只没有尾巴';
            console.log("第三段");
            yield '真奇怪';
            console.log("第四段");
        }
        // 实现了迭代器接口 遍历
        for (let v of gen()) {
            console.log(v);
        }

image-20220415165356660

生成器函数的参数传递:

    <script>
        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());
        // next方法可以传入实参
        console.log(iterator.next('BBB'));//将作为第1个yield语句的整体返回结果
        console.log(iterator.next('CCC'));//将作为第2个yield语句的整体返回结果
        console.log(iterator.next('DDD'));//将作为第3个yield语句的整体返回结果
    </script>

生成器案例:

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

        // 异步编程 文件操作 网络操作 数据库操作
        // 需求:1s后控制台输出111 2s后控制台输出222 3s后控制台输出333
        // 定时器嵌套实现:
        // 回调地狱
        setTimeout(()=>{
            console.log(111);
            setTimeout(()=>{
                console.log(222);
                setTimeout(() => {
                    console.log(333);
                }, 3000);
            },2000)
        },1000)
        // 生成器函数实现:
        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();

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

//数据有关联度度:用户数据=>订单数据=>商品数据

function one(){
    setTimeout(()=>{
        let data='用户数据';
        iterator.next(data)//第二次调用next 实参将作为第一个yield语句的返回结果
    },1000)
}
function two(){
    setTimeout(()=>{
        let data='订单数据';
        iterator.next(data)//第三次调用next 实参将作为第二个yield语句的返回结果
    },2000)
}
function three(){
    setTimeout(()=>{
        let data='商品数据';
        iterator.next(data)//第四次调用next 实参将作为第三个yield语句的返回结果
    },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();

13.Promise

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

在这里插入图片描述

Promise基本使用:

        // 实例化Promise对象p  三个状态:初始化,成功,失败
        const p = new Promise(function(resolve,reject) {
            setTimeout(function(){
                // 
                let data = '数据库中的数据'
                // resolve
                // resolve(data);//调用resolve后对象p的状态变为成功
                
                let err = '数据读取失败';
                reject(err);//promise状态变为失败
            },1000)
        })
        // 调用Promise对象的then方法
        p.then(function(success){//promise状态变为成功后then会调用第一个回调函数
            console.log(success);
        },function(err){//promise状态变为失败后then会调用第二个回调函数
            console.error(err);
        })

Promise读取文件:

在这里插入图片描述

promise读取文件.js

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

// 2.调用方法读取文件
fs.readFile('./resource/悯农.md',(err,data)=>{
    // 如果失败,则抛出错误
    if(err) throw err;
    // 如果成功。则输出内容
    console.log(data.toString());
})

在这里插入图片描述

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

// 2.调用方法读取文件
// fs.readFile('./resource/悯农.md',(err,data)=>{
//     // 如果失败,则抛出错误
//     if(err) throw err;
//     // 如果成功。则输出内容
//     console.log(data.toString());
// })

// 3.使用Promise封装
const p = new Promise(function(resolve,reject){
    fs.readFile("./resource/悯农.mda",(err,data)=>{
        // 判断如果失败
        if(err) reject(err);
        // 成功
        resolve(data);//更改promise状态为成功,通过data传参
    })
})
p.then(function(success){
    console.log(success.toString());
},function(err){
    console.log("读取失败!");
})

在这里插入图片描述

Promise封装AJAX:

<!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>Document</title>
</head>

<body>
    <script>
        // 接口地址:https://api.apiopen.top/getJoke

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

        // 指定回调
        p.then(function (success) {
            console.log(p);
            console.log(success);
        }, function (err) {
            console.log(p);
            console.log(err);
        })
    </script>
</body>

</html>

image-20220416132027441

Promise对象 then方法:

<!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>Document</title>
</head>
<body>
    <script>
        // 创建promise对象
        const p = new Promise(function(resolve,reject){
            setTimeout(()=>{
                resolve('用户数据')
                // reject('出错啦')
            },1000)
        })
        // 调用then方法 返回结果result也是一个promise对象 对象状态由函数的执行结果决定
        //1. 如果回调函数中返回的结果是 非promise类型的数据,result状态为成功,PromiseResult为该回调函数的返回值
        //2. 如果回调函数中返回的结果是promise类型的数据,result状态跟随回调函数的状态,PromiseResult为该回调函数的返回值
        //3. 抛出错误,result状态为rejected,PromiseResult为回调函数抛出的错误值
        const result = p.then(success=>{
            console.log(p);//PromiseState:rejected
            // console.log(success);
            
            // 1.非promise对象
            // return 123;

            // 2.是promise对象
            // return new Promise((resolve,reject)=>{
            //     resolve('ok');//result: PromiseResult:'ok'
            //     // reject('err');//result: PromiseResult:'err'
            // })

            // 3.抛出错误
            throw new Error("出错啦!");//PromiseState: "rejected"  | PromiseResult: Error:
        },err=>{
            console.log(p);//PromiseState:fulfilled
            console.warn(err);
        })
        console.log(result);
    </script>
</body>
</html>

因为then方法的这些特性,所以then方法可以链式调用

        // 链式调用 可以解决回调地狱的现象
        p.then(value=>{

        },reason=>{

        }).then(value=>{

        },reason=>{
 

catch方法:

用来指定promise失败的回调

    <script>
        const p = new Promise((resolve,reject)=>{
            setTimeout(()=>{
                // 设置p对象的状态为失败,并设置失败的值
                reject('出错!');
            })
        },1000)

        // p.then(success=>{
        //     console.log(success);
        // },err=>{
        //     console.log(err);
        // })
        // console.log(p);

        p.catch(err=>{
            console.warn(err);
        })
        console.log(p);
    </script>

promise实践(解决回调地狱):

依次读取悯农,悯农1,悯农2,最后三个内容合在一起输出

// 引入fs模块
const fs = require("fs")
const { resolve } = require("path")

// 回调地狱 实际当中不会这样做,但会有这样的层级
// fs.readFile('./resource/悯农.md', (err, data1) => {
//     fs.readFile('./resource/悯农1.md', (err, data2) => {
//         fs.readFile('./resource/悯农2.md', (err, data3) => {
//             let result = data1 + '\r\n' + data2 + '\r\n' + data3
//             console.log(result);
//         })
//     })
// })

// 使用Promise实现
const p = new Promise((resolve, reject) => {
    fs.readFile("./resource/悯农.md", (err, data) => {
        resolve(data);
    })
})

p.then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./resource/悯农1.md", (err, data) => {//这个方法成功,then方法返回的promise也是成功的
            resolve([value, data]);//合并
        })
    })
}).then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./resource/悯农2.md", (err, data) => {
            value.push(data);
            resolve(value);
        })
    })
}).then(value=>{
    console.log(`${value}`);
})

image-20220416144356110

14.set

  • 集合介绍与Api

在这里插入图片描述

        //声明一个set
        let s = new Set();
        let s2 = new Set(['1','2','3','3','5','5']); //自动去重
        console.log(s, typeof s);
        console.log(s2);

        // // 元素个数
        // console.log(s2.size);
        // // 添加新元素
        // s2.add('a');
        // console.log(s2);
        // // 删除元素
        // s2.delete('a');
        // console.log(s2);
        // // 检测 存在为true
        // console.log(s2.has('1'));
        // // 清空
        // s2.clear();
        // console.log(s2);

        for (let v of s2) {
            console.log(v);
        }
  • 集合实践
        //集合实践
        let arr = [1,2,3,4,5,4,3,2,1];

        // 1.数组去重
        // let result = [...new Set(arr)];
        // console.log(result);  //[1, 2, 3, 4, 5]
        // 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;
        //     }
        // })
        // console.log(result);

        // 简化
        // 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);//1 2 3 4 5 6

        // 4.差集  就是交集的取反
        let result = [...new Set(arr)].filter(item=>!new Set(arr2).has(item));
        console.log(result);

15.Map的介绍和API

在这里插入图片描述

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

        // 添加元素 set
        m.set('name','小明');
        console.log(m);

        let key = {
            school:'清华'
        };
        m.set(key,['北京','上海'])//key是对象,值是数组
        console.log(m);

        // 获取元素个数 size
        console.log(m.size);//2
        // 删除元素 delete
        // m.delete('name');
        // console.log(m);
        // 获取 get
        console.log(m.get('name'));

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

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

16.class

在这里插入图片描述

  • class的介绍与初体验
        /*         // 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 Phone {
            // 构造方法  名字不能修改
            constructor(brand, price) {
                this.brand = brand;
                this.price = price
            }
            // 方法必须使用该语法,不能使用ES5的对象完整形式
            call(){
                console.log("打电话!");
            }
        }
        // 实例化
        let Huawei = new Phone('huawei',1999);
        console.log(Huawei);
        Huawei.call();
  • class静态成员
/*         // ES5
        function Phone() {

        }
        Phone.name = '手机';
        Phone.change = function () {
            console.log("我可以打电话");
        }
        Phone.prototype.size='5.5inch'
        console.log(Phone.prototype);

        let nokia = new Phone();
        console.log(nokia.name);//unfidend | 实例对象是没有构造函数对象上面的属性的
        // nokia.change();//报错
        console.log(nokia.size);//5.5inch */

        class Phone{
            // 静态属性  属于类不属于实对象
            static name = '手机';
            static change(){
                console.log('我能打电话');
            }
        }
        let nokia = new Phone();
        console.log(nokia.name);//undefined
        console.log(Phone.name);//手机
  • 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);//通过call方法改变this值 this指向SmartPhone
            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 chuzi = new SmartPhone('锤子',2499,'黑色','5inch');
        console.log(chuzi);

在这里插入图片描述

  • ES6类继承
        class Phone {
            // 构造方法
            constructor(brand, price) {
                this.brand = brand;
                this.price = price;
            }
            // 父类的成员属性
            call(){
                console.log("我可以打电话!");
            }
        }
        
        class SmartPhone extends Phone{//extends关键字继承父类Phone
            // 构造方法
            constructor(brand, price,color,size){
                super(brand,price)//super调用父类的构造方法
                this.color=color;
                this.size=size;
            }
            photo(){
                console.log("拍照");
            }
            playGame(){
                console.log("玩游戏");
            }
        }
        // 实例化
        const xiaomi = new SmartPhone('小米',499,'黑色','4.7inch');
        console.log(xiaomi);

image-20220417155556105

  • ES6子类重写父类方法
        class Phone {
            // 构造方法
            constructor(brand, price) {
                this.brand = brand;
                this.price = price;
            }
            // 父类的成员属性
            call(){
                console.log("我可以打电话!");
            }
        }
        
        class SmartPhone extends Phone{//extends关键字继承父类Phone
            // 构造方法
            constructor(brand, price,color,size){
                super(brand,price)//super调用父类的构造方法
                this.color=color;
                this.size=size;
            }
            photo(){
                console.log("拍照");
            }
            playGame(){
                console.log("玩游戏");
            }
            call(){//重写了父类的call方法
                // 注意子类是不能直接调用父类的重名方法的
                console.log("视频通话");
            }
        }
        // 实例化
        const xiaomi = new SmartPhone('小米',499,'黑色','4.7inch');
        console.log(xiaomi);
        xiaomi.call();//视频通话
  • class的getter和setter
        // get和set
        class Phone{
            get price(){
                console.log("价格属性被读取");
                return '价格'
            }
            set price(newPrice){//setter 必须有参数
                console.log("价格属性被修改");
            }
        }
        // 实例化对象
        let s = new Phone();
        // console.log(s.price);
        s.price = "免费";//执行setter
        // console.log(s.price);

17.ES6的数值拓展

        // 0. Number.EPSILON是接近于JavaScript表示的最小精度
        // Number.EPSILON属性的值接近于2.2204460492503130E-16
        // 主要用于浮点数的运算
        console.log(0.1 + 0.2);//0.30000000000000004
        console.log(0.1 + 0.2 === 0.3);//false
        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));//true

        // 1. 进制的表示
        let b = 0b1010;//二进制的10
        let o = 0o777;//八进制的511
        let d = 100;//十进制
        let x = 0xff//十六进制的255

        // 2. NUmber.isFinite 检测一个数值是否为有限数
        console.log(Number.isFinite(100));//true
        console.log(Number.isFinite(100/0));//false
        console.log(Number.isFinite(Infinity));//false  Infinity表示无穷
        // 3. Number.isNaN  检测一个数值是否为NaN
        console.log(Number.isNaN(123));//false
        // 4.Number.parseInt | Number.parseFloat 字符串转换为数字
        console.log(Number.parseInt('5211314love'));//5211314
        console.log(Number.parseFloat('3.1415926abcde'));//3.1415926
        // 5. Number.isInteger 判断一个数是否为整数
        console.log(Number.isInteger(5));//true
        console.log(Number.isInteger(2.5));//false
        // 6. Math.trunc 将数字的小数部分抹掉
        console.log(Math.trunc(3.5));//3
        // 7. Math.sign 判断一个数为正数 负数 还是零 分别返回1 0 -1
        console.log(Math.sign(100));//1
        console.log(Math.sign(0));//0
        console.log(Math.sign(-2000));//-1

18.ES6对象方法的拓展

        // 1. Object.is  判断两个值是否完全相等 
        console.log(Object.is(120, 120));//true
        console.log(Object.is(NaN, NaN));//true
        console.log(NaN === NaN);//false
        // 2.Object.assign(a,b)  对象的合并 第一个参数为模板,第二个参数为覆盖的内容 b覆盖a
        const config1 = {
            host: 'localhost',
            port: 3306,
            name: 'root',
            pass: 'root',
            test: 'test'
        }
        const config2 = {
            host: 'https://baidu.com',
            port: 3366,
            name: 'baidu',
            pass: 'baidu'
        }
        console.log(Object.assign(config1, config2));
        // host: "https://baidu.com"
        // name: "baidu"
        // pass: "baidu"
        // port: 3366
        // test: "test"

        // 3. Object.setPrototypeOf 设置原型对象 | Object.getPrototypeOf 获取原型对象
        const school = {
            name:"清华"
        }
        const cities = {
            area:['北京','上海','深圳']
        }
        Object.setPrototypeOf(school,cities);
        console.log(school);
        console.log(Object.getPrototypeOf(school));

在这里插入图片描述

19.ES6模块化

1.模块化的介绍

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

模块化的好处:

  • 防止命名冲突
  • 代码复用
  • 高维护性

模块化规范产品:

image-20220417170730688

2.模块化语法

模块化语法主要由两个命令构成:export和import

  • export命令用于规定模块的对外接口
  • import命令用于输入其他模块提供的功能

image-20220417172418112

在这里插入图片描述

3.ES6模块暴露数据语法汇总

  • 分别暴露:如上

  • 统一暴露

// 统一暴露
let school = '北大';

function findJob(){
    console.log("找工作");
}

export {school,findJob} 
  • 默认暴露
// 默认暴露
export default {
    school:'复旦',
    change(){
        console.log('改变你');
    }
}

index.html

<!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>Document</title>

</head>
<body>
    <script type="module">
        // 引入m1.js模块的内容
        import * as m1 from './js/m1.js'
        import * as m2 from './js/m2.js'
        import * as m3 from './js/m3.js'
        console.log(m1);//出现跨域问题 安装live serve插件 右键open with live Serve打开
        console.log(m2);
        console.log(m3);
        m3.default.change();//改变你
    </script>
</body>
</html>

4.ES6模块引入模块数据语法汇总

        // 1.通用的导入方式
        // 引入m1.js模块的内容
        // import * as m1 from './js/m1.js'
        // import * as m2 from './js/m2.js'
        // import * as m3 from './js/m3.js'
        // console.log(m1);//出现跨域问题 安装live serve插件 右键open with live Serve打开
        // console.log(m2);
        // console.log(m3);
        // m3.default.change();//改变你

        // 2.解构赋值形式
        import {school,teach} from './js/m1.js'
        import {school as m2School,findJob} from './js/m2.js'
        console.log(school);
        console.log(teach);

        console.log(m2School);
        console.log(findJob);

        // 3.简便形式,只针对默认暴露
        import m3 from './js/m3.js'
        console.log(m3);

5.浏览器使用ES6模块化方式二

创建入口文件 app.js

// 入口文件 

// 模块引入
import * as m1 from './m1.js'
import * as m2 from './m2.js'
import * as m3 from './m3.js'

console.log(m1);
console.log(m2);
console.log(m3);

index.html只需引入入口文件

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

    </script>

20.ES7新特性

  • 数组的includes方法:判断数组是否包含此元素
        // includes
        const mingzhu = ['西游记', '三国演义', '水浒传']
        // 判断
        console.log(mingzhu.includes('西游记'));//true
        console.log(mingzhu.includes('金瓶梅'));//false
        // indexof也能判断
        console.log(mingzhu.indexOf('西游记'));//存在返回0
        console.log(mingzhu.indexOf('金瓶梅'));//不存在返回-1
  • 幂运算:**
        // **
        console.log(2 ** 10);//1024
        console.log(Math.pow(2,10));//1024

21.ES8新特性(async和await)

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

理解 JavaScript 的 async/await - SegmentFault 思否

async函数:

  • async函数的返回值为promise对象

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

        // async函数
        async function fn(){
            // 只要返回的不是一个promise对象,则结果就是成功的promise对象,状态为resolved(或fulfilled),返回值就是函数返回值
            // return 'async'

            // 抛出错误 返回的结果是一个失败的promise
            // throw new Error('出错啦');

            // 返回的结果是一个promise对象 则返回值与return语句的promise对象一样
            return new Promise((resolve,reject)=>{
                resolve('成功的数据')
                // reject('失败的数据')
            })
        }
        const result = fn();
        console.log(result);

        // 调用then方法
        result.then(success=>{
            console.log(success);
        },err=>{
            console.log(err);
        })

await函数:

  • await必须写在async函数中
  • await右侧的表达式一般为promise对象
  • await返回的是promise成功的值
  • await的promise失败了,就会抛出异常,需要通过try…catch…捕获处理
        // await 必须放在async函数中。但是async可以没有await,不过一般都写在一起
        // 创建promise对象
        const p = new Promise((resolve, reject) => {
            // resolve("成功的值");
            reject("失败了!");
        })

        // await要放在async函数中
        async function main() {
            try {
                let result = await p;
                console.log(result);
            } catch (error) {
                // 对失败的结果进行处理
                console.log(error);
            }
        }
        // 调用函数main
        main();

async和await结合读取文件

在这里插入图片描述

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

// 读取悯农
function read(){
    return new Promise((resolve,reject)=>{
        fs.readFile("./resource/悯农.md",(err,data)=>{
            // 如果失败就把返回的promise对象的状态变为失败的状态
            if(err) reject(err);
            // 如果成功 就把返回的promise对象的状态变为成功,将数据传入
            resolve(data)
        })
    })
}

// 读取悯农1
function read1(){
    return new Promise((resolve,reject)=>{
        fs.readFile("./resource/悯农1.md",(err,data)=>{
            // 如果失败就把返回的promise对象的状态变为失败的状态
            if(err) reject(err);
            // 如果成功 就把返回的promise对象的状态变为成功,将数据传入
            resolve(data);
        })
    })
}

// 读取悯农2
function read2(){
    return new Promise((resolve,reject)=>{
        fs.readFile("./resource/悯农2.md",(err,data)=>{
            // 如果失败就把返回的promise对象的状态变为失败的状态
            if(err) reject(err);
            // 如果成功 就把返回的promise对象的状态变为成功,将数据传入
            resolve(data)
        })
    })
}

// 声明一个async函数
async function main(){
    //返回结果为promise对象,用await接收
    let result = await read();
    let result1 = await read1();
    let result2 = await read2();

    console.log(result.toString());
    console.log(result1.toString());
    console.log(result2.toString());
}
// 调用main()
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(success=>{
        //     console.log(success);
        // },err=>{
        //     console.log(err);
        // })

        // async与await测试
        async function main(){
            // 发送AJAX请求
            let result = await sendAJAX('https://api.apiopen.top/getJoke');
            console.log(result);
        }
        main();

22.ES8对象方法拓展

在这里插入图片描述

        // 声明对象
        const school = {
            name: "北大",
            citys: ['北京', '上海', '深圳'],
            subjects: ['语文', '数学', '英语']
        }
        // 获取对象所有的键
        console.log(Object.keys(school));//['name', 'citys', 'subjects']
        // 获取对象所有的键
        console.log(Object.values(school));//['北大', Array(3), Array(3)]
        // entries
        console.log(Object.entries(school));//[Array(2), Array(2), Array(2)]
        // 创建Map
        const m = new Map(Object.entries(school));
        console.log(m);
        // 对象属性的描述对象
        console.log(Object.getOwnPropertyDescriptors(school));

        const obj = Object.create(null,{
            name:{
                // 设置值
                value:'清华',
                // 属性的特性
                writable:true,
                configurable:true,
                enumerable:true
            }
        })

29.ES9

1.对象的Rest参数与spread拓展运算符

Rest参数与spread拓展运算符在ES6中已经引入。步过ES6中只针对于数组

在ES9中为对象提供了像数组一样的rest参数和拓展运算符

        // 1.reset参数
        // 剩余的参数作为user对象传入 ...user只能写在最后
        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'
        });

        // 2.拓展运算符
        const skill1 = {
            q:'天音波'
        }
        const skill2 = {
            w:'金钟罩'
        }
        const skill3 = {
            e:'天雷蛇'
        }
        const skill4 = {
            r:'神龙摆尾'
        }
        // 将四个对象合并成一个对象
        const hero = {...skill1,...skill2,...skill3,...skill4}
        console.log(hero);

30.ES10

1.对象拓展方法Object.fromEntries

用来创建一个对象,接受一个二维数组或者map

        // 接受二维数组
        const result = Object.fromEntries([
            ['name','小明'],
            ['school','清华,北大,哈佛']
        ]);
        console.log(result);//{name: '小明', school: '清华,北大,哈佛'}

        // 接收Map
        const m = new Map();
        m.set('name','小红');
        const result2 = Object.fromEntries(m);
        console.log(result2);//{name: '小红'}

        // Object.fromEntries相当于ES8中的Object.entries方法的逆运算
        // 接收一个对象,将对象转化为二维数组
        const arr = Object.entries({
            name:'小兰'
        })
        console.log(arr);

2.字符串方法拓展:trimStart和trimEnd

        // ES5中存在trim方法,用来清除字符串两侧的空白字符
        // ES10中trimStart和trimEnd用来清除指定字符左侧或右侧的空白字符
        let str = '      hello     ';

        console.log(str);//      hello     ;
        console.log(str.trim());//hello;
        console.log(str.trimStart());//hello     ;
        console.log(str.trimEnd());//      hello;
    </script>

3.数组方法拓展:flat和flatMap

        // flat(n):将多维数组转化为低维数组,n表示为深度,默认为1
        const arr = [1, 2, 3, 4, [5, 6]];//二维数组
        console.log(arr.flat());//[1, 2, 3, 4, 5, 6]

        const arr2 = [1, 2, 3, 4, [5, 6, [7, 8, 9]]];//三维数组
        console.log(arr2.flat());//[1, 2, 3, 4, 5, 6, [7,8,9]]
        console.log(arr2.flat(2));//[1, 2, 3, 4, 5, 6, 7, 8, 9]

        // flatMap
        const arr3 = [1, 2, 3, 4];
        // map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
        const result = arr3.map(item => item * 10);
        console.log(result);//[10, 20, 30,40]

        // flatMap() 方法是 flat() 和 map() 方法的组合。此方法最初通过映射函数映射每个数组元素,然后将深度值为 1 的数组展平。
        const result2 = arr3.map(item => [item * 10]);
        console.log(result2);//返回二维数组 [Array(1), Array(1), Array(1), Array(1)]
        const result3 = arr3.flatMap(item => [item * 10])
        console.log(result3);//[10, 20, 30, 40]

4.symbol拓展:symbol. prototype.description

        // Symbol.prototype.description:获取Symbol的字符串描述
        let s = Symbol('清华');
        console.log(s.description);

31.ES11

1.私有属性

私有属性用 # 修饰

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

            // 参考java的set get方法
            intro() {
                console.log(this.name);
                console.log(this.#age);
                console.log(this.#weight);
            }
        }
        // 实例化
        const girl = new Person('小明', 18, '45kg');
        console.log(girl);//Person {name: '小明', #age: 18, #weight: '45kg'}
        console.log(girl.name);//小明
        console.log(girl.age);//undefind
        console.log(girl.weight);//undefind

        girl.intro();//小明 18 45kg

2.Promise.allSettled方法

接收promise数组,返回结果永远是成功状态,结果值根据每一个promise对象的值

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

        // 调用allsetted方法
        const result = Promise.allSettled([p1,p2])
        console.log(result);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hUitzK57-1650611396441)(http://division-222.gitee.io/typora-user-images/image-20220418100402308.png)]

之前的all方法和allsetted方法很像,区别在于all方法中,promise数组中的状态都为成功时,才返回成功状态

        // 之前的all方法和allsetted方法很像
        const result2 = Promise.all([p1,p2]);
        console.log(result2);

3.String.prototype.matchAll方法

用来得到正则批量匹配的结果

4.可选链操作符

符号: [ ?. ]

作用: 当使用对象类型参数时,可以省去层级的判断

        // ?.
        function main(config) {
            // 原来的判断
            /* 
                注意:
                1、只要 || 前面为 false,无论 || 后面是true还是 false,结果都返回 || 后面的值。
                2、只要 || 前面为 true,无论 || 后面是true还是 false,结果都返回 || 前面的值。
                3、只要 && 前面是 false,无论 && 后面是true还是 false,结果都将返 && 前面的值;
                4、只要 && 前面是 true,无论 && 后面是true还是false,结果都将返 && 后面的值;
            */
            // const dbHost = config && config.db && config.db.host;
            // const dbHost = config.db.host;//如果不判断 到时候要是没有传递该属性会报错
            // console.log(dbHost);

            //前边的属性存在,再去读取?.后的的属性
            const dbHost = config?.db?.host;
            console.log(dbHost);
        }

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

5.动态import

可以实现按需加载,节约资源

image-20220418104803371

hello.js

export function hello() {
    alert('hello')
}

app.js

// 动态import
// 获取元素
const btn = document.getElementById('btn');

btn.onclick = function(){
    // import动态引入,预加载,使用的时候再引入
    import('./hello.js').then(module => {
        console.log(module);
        module.hello();
    })
}
<!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>Document</title>
</head>
<body>
    <button id="btn">点击</button>
    <script src="./js/app.js"></script>

</body>
</html>

6.BigInt大整型

表示方法:在整形数字后加n

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

7.绝对全局对象globalThis

无论执行环境是什么,始终指向全局对象

    <script>
        console.log(globalThis);//Window
    </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值