自学内容网 自学内容网

前端复习(二)

ES6

2015 年发布的ECMAScript 2015,也叫 ECMAScript 6,简称为 ES6。

https://www.kancloud.cn/pwstrick/fe-questions/1094971

const、let

  • const:定义常量(不可二次赋值)

  • let:定义局部变量(作用域为{})

运算符

  • 展开运算符: ... 表示展开运算符,可以把数组和对象中的值展开。

    let [a,b,...c] = [1,2,3,4,5,6,7];
    document.write(a)   //1
    document.write(b)   //2
    document.write(c)   //3,4,5,6,7
    document.write(c instanceof Array) //true

模板字面量

模板字面量(Template Literal)是一种能够嵌入表达式的格式化字符串,有别于普通字符串,它使用反引号(`)包裹字符序列,而不是双引号或单引号。模板字面量包含特定形式的占位符(${expression}),由美元符号、大括号以及合法的表达式组成,合法的表达式(expression)可以是变量、算术或函数调用,甚至还可以是模板字面量。模板字面量无需为双引号或单引号转义,但如果出现反引号,那么就得将其转义。

let info = "少年";
let msg = `归来仍是 ${info}`;
document.write(msg)     //归来仍是 少年
  • 占位符 ${expression}

    在占位符内,表达式的计算结果会按照一定的规则转换成字符串,如果计算结果是数字、布尔值、对象或数组等,那么就调它们内置的toString()方法;而如果是null或undefined,那么就用String()函数实现类型转换。

    `${"abc"}`;         //"abc"
    `${123}`;           //"123"
    `${true}`;          //"true"
    `${null}`;          //"null"
    `${undefined}`;     //"undefined"
    `${{ id: 1 }}`;     //"[object Object]"
    `${[1, 2, 3]}`;     //"1,2,3"
  • 多行字符串

    模板字面量中的字符串会保持原样输出,包括空格、换行符等。对于多行字符串的处理,不必像单引或双引号那样进行换行符(”\n“)拼接。

  • 标签模板

    标签模板并不是模板,而是一种特殊方式的函数调用。示例:

    func`<p>${name}</p><p>${age}</p>`

    调用func()函数的时候省略了圆括号,函数名后面直接跟模板字面量,这就是标签模板的调用方式。

    它一般会包含两个参数,第一个是由没有被替换的部分组成的数组,第二个是剩余参数,包含了所有占位符中的计算结果。 一个完整的标签模板的示例 :

    let name = "libai";
    let age = 20;
    function func(literals, ...substitutions){
        console.log(literals);      //["<p>", "</p><p>", "</p>", raw]
        console.log(substitutions); //["libai", 20]
    }
    func `<p>${name}</p><p>${age}</p>`;

解构

  • 对象解构

    对象的解构是将对象赋值给一组对象字面量,即按同名(必须)原则,将对象属性赋值给一组同名的量。

    const User = {
        name:"libai",
        pwd:"123456"
    };
    //      解构对象       原对象
    const { name, pwd } = User;
    ​
    document.write(name)    //等价 User.name
    document.write(pwd)     //等价 User.pwd

    给解构对象中的值赋予新的变量名,就是在对象中关键字冒号后面放上新的变量名。赋予新名后,原名字将无法再使用。

    const User = {
        name:"libai",
        pwd:"123456"
    };
    const { name:userName, pwd:userPwd } = User;
    document.write(userName)    //不能再使用 name
    document.write(userPwd)     //不能再使用 pwd

    复杂对象解构示例:

    const Users = {
        user1:{
            name:"libai",
            pwd:"123456"
        },
        user2:{
            name:"dufu",
            pwd:"999999"
        }
    };
    const {user1,user2} = Users;
    document.write(user1.name)
    document.write(user2.name)
  • 数组解构

    数组是根据元素的顺序来解构的,可以看成一种模式匹配,等号左右两边变量与值的个数相同便能匹配成功。

    let arr = [1,2,3];
    let [a,b,c] = arr;
    document.write(a + " " + b + " " + c)   //1 2 3
    ​
    let [m,,n] = arr;
    document.write(n)   // 3

    还可以在数组解构赋值的表达式中为数组里任意位置添加默认值。当指定位置的值为 undefined 或者不存在时,使用其默认值。

    let [name1,name2="杜甫"] = ["李白"];
    document.write(name1)   //李白
    document.write(name2)   //杜甫

代码模块化

一个模块就是一个独立的JavaScript文件。

export

关键字 export 可以将一个模块中的常量、变量、函数或类(ES6新增的概念)等从模块中输出,允许其他需要的模块按指定的标准进行访问,没有使用关键字 export 输出的模块内容,是封闭的,其它模块无法访问到它,下面介绍关键字 export 几种输出的方式 。

  1. 命名导出(每个模块包含任意数量)

    outer1.js:

    //导出 1 个
    export let name = "admin";
    export function setName(newName){
        name = newName;
    }

    outer2.js:

    let name = "admin";
    function setName(newName){
        name = newName;
    }
    //导出 多个
    export {name, setName}

    outer3.js:

    //别名(重命名)导出 : 调用者模块只能使用别名
    export {name as username, setName as setUsername}
  2. export from

    outer4.js:

    /**
     * 下面的 export 等价于:
     * import {name, setName} from "./outer1.js"
     * export {name, setName}
     */
    export {name, setName} from "./outer1.js"
    ​
    // 部分导出并取别名
    export {name as username, setName as setUsername} from "./outer1.js"
    ​
    // 一次导出全部
    export * from "./outer1.js"
  3. 默认导出(每个模块包含一个)

    export语句中的default其实就是要导出的模块成员,它的名称就叫default,而default后面能够跟一个表达式、命名函数或匿名函数 。

    outer5.js:

    //导出量
    export default  name = "admin";             //方式1
    export default "admin";                     //方式2
    export {name as default}                    //方式3
    ​
    //导出方法
    export default function setName(newName){   //方式1
        name = newName;
    }
    export default setName(newName){            //方式2
        name = newName;
    }
    export {setName as default}                 //方式3

import

与关键字 export 相对应,import 的功能是输入已经使用关键字 export 输出的内容,它们是对应关系, export 负责输出,而 import 则用于接受输出的内容,即负责输入 。

import导入的变量都是只读的,相当于为它添加了const限制 。 想要更新导入的变量的值 ,可以像上面的outer1.js 那样,为变量提供一个 setter 方法,间接达到更新的目的。

  1. 命名导入: 导入部分

    //1. from 后面路径中的 ./ 不能省
    import {name,setName} from './outer1.js';
    //2. 
    import {name,setName} from './outer2.js';           
    console.log(name);          //输出:admin
    setName("aaa");
    console.log(name);          //输出:aaa
    ​
    //3. 
    import {username,setUsername} from './outer3.js';
    console.log(username);      
    setUsername("bbb");     
    ​
    //4. 给导入元素取别名
    import {name as username, setName as setUsername } from './outer1.js';
    console.log(username);
    setUsername("ccc");
  2. 命名空间导入:导入全部

    与导出模块的全部成员不同,在导入时,除了要与星号组合之外,还必须为其设置别名。这是由于加载的整个模块会被当成一个对象,而此对象需要一个名称,它的属性就是该模块所有的导出。

    import * as user from './outer1.js';
    console.log(user.name); 
    user.setName("ddd");
  3. 默认导入:导入默认导出的值

    //由于默认导出每个模块只有一个,所以导入时名字可以任意,下面的 name 也可以叫 a 或 abc 之类的。
    import name from './outer5.js';
    ​
    //当同时导入默认和非默认的导出值时,必须把默认的写在前面
    import name,{pwd} from './outer5.js';
  4. 简洁导入:执行js文件中可执行代码

    //outer6.js
    console.log("test")
    ​
    //在test.html 页面中 import './outer6.js',控制台输出:test
    import './outer5.js'

示例

model.js:

export let name = "admin";
export let pwd = "123456";

service.js:

import {name, pwd} from "./model.js"
​
function checkName(){
    console.log("管理员登录")
}
​
function checkPwd(){
    console.log("密码正确")
}
​
export {checkName, checkPwd };

test.html:

<!--type 属性值设置为 module ,表示代码中允许使用模块输入和输出的关键字,进行模块化代码开发。-->
<script type="module">
    import {checkName,checkPwd} from "./js/service.js";
    checkName();
    checkPwd()
​
    /* import * as checker from "./js/service.js";
       checker.checkName();
       checker.checkPwd();
    */
</script>

箭头函数

箭头函数(Arrow Function)由三部分组成:箭头(=>)、参数和函数体,省略了名称和function关键字。

//参数和箭头要在一行中,不能换行,并且没有箭头函数声明,只有箭头函数表达式。 
let test1 = () => {
    console.log(1);
}
test1();                //输出 1
​
//如果函数体中只包含一个表达式,可以省略花括号和return关键字
let test2 = (num) => 2 + num;
let n = test2(1);       //n == 3

Promise

Promise是ES6新增的特性,能更合理的控制和追踪异步操作。它是一个包含状态、可继承的对象,不仅能管理而不是依赖回调,还能以同步的方式传递异步的计算结果,从而避免陷入回调的泥潭中。链式(即串联起来)的Promise 让代码有更高的可读性和更便捷的调试性。

使用 Promise - JavaScript | MDN (mozilla.org)

  • 状态 Promise依据其状态的变化,让异步操作变得有序,而Promise有三种互斥的状态,具体如下:

  (1)pending:等待中,初始状态,此时还未处理(Promise中的)异步操作。

  (2)fulfilled:已完成,异步操作成功时的状态。

  (3)rejected:已拒绝,异步操作失败时的状态。

  • 创建

    如果要使用Promise,那么需要先初始化,可以通过构造函数的方式创建一个Promise实例,如下所示。

    let promise = new Promise(function(resolve, reject) {
      /* executor */
    });
    

    构造函数 Promise() 能接收一个执行器(executor),即带有resolvereject两个参数的函数。执行器会在构造函数返回新实例前被调用。它的两个参数也是函数,分别适合不同的语境,具体如下:

      (1)在执行器中的异步操作完成时会调用resolve()函数,当前 Promise的状态会根据它的参数发生变化。当参数为空或非Promise时,当前状态变成fulfilled;当参数是Promise时,当前Promise的状态和参数的相同。

      (2)在执行器中的异步操作错误时会调用reject()函数,当前Promise的状态会变成rejected

      resolve()reject()都能接收一个参数(即决议结果),前者的参数可以是本次操作的结果;而后者的参数可以是操作失败的原因,它们都会传递给下一个异步操作。

  • then()

    在生成Promise实例之后,就能通过then()方法绑定状态变化后的回调函数(即处理方法),如下代码所示,此处是异步操作同步化的关键。

    promise.then(function(value) {
      // success
    }, function(reason) {
      // failure
    });
    

    then()方法的两个参数,可分别指定状态变成fulfilledrejected后的回调函数,而这两个回调函数的参数分别来自于resolve()和reject()函数。通过then()方法的这两个回调函数就能清晰的反馈出异步操作是否成功执行。

    then()方法的返回值是一个新的Promise实例,因此可以链式调用then()方法,按顺序绑定回调函数 :

    /*
    Promise: 承诺 - 需求
    resolve: 兑现 - 执行完毕:ok
    reject: 拒绝 - 中途中断:error
    */
    new Promise(function(resolve,reject){
        resolve("OK");
    }).then(
        //1. resolve callback
        function(result){
            console.log(result)//输出:OK
            return Promise.resolve("OK2");
        },
        //2. reject callback
        function(reason){
            console.log(reason)
            return Promise.reject("error");
        }
    ).then(
        function(result){
            console.log(result)//输出:OK2
            return "OK3";
        },
        null//无处理失败的回调函数
    ).then(
        function(info){
            console.log(info);//输出:OK3
            return Promise.reject("error2");
        }
        // 省略处理失败的回调函数
    ).then(
        null,
        function(info){
            console.log(info);//输出:error2
            return Promise.reject("error3");
        }
    )
    // 总是使用 catch 终止 Promise 链,以保证任何未处理的拒绝事件都能被捕获!
    .catch(function(reason){
        console.log(reason);//输出:error3
    });
    

ES7 ~ ES12

ES7

  • Array.prototype.includes() 方法用来判断数组中是否包含指定元素,返回值是布尔类型 true 或者 false 。

  • 指数操作符 **

    let m = 2 ** 3;     // m == 8
    let n = 2;
    n **= 3;            // n == 8

ES8

  • async/await 异步终极解决方案。

    async function 声明创建一个绑定到给定名称的新异步函数。函数体内允许使用 await 关键字,这使得我们可以更简洁地编写基于 promise 的异步代码,并且避免了显式地配置 promise 链的需要。

    异步函数可以包含零个或者多个 await 表达式。await 表达式通过暂停执行使返回 promise 的函数表现得像同步函数一样,直到返回的 promise 被兑现或拒绝。返回的 promise 的解决值会被当作该 await 表达式的返回值。使用 async/await 关键字就可以使用普通的 try/catch 代码块捕获异步代码中的错误

    async function func(){
        console.log(1);
        let ret = await new Promise((resolve) => {  //ret == 9
            setTimeout(() => {
                console.log(2);
                resolve(9);
            },2000);
        });
        console.log(3);
    }
    func(); //输出:1 2 3,去掉 await 输出 1 3 2 

    async/awiat的使用规则:

    • async 表示这是一个异步函数, await只能用在async函数里面,不能单独使用

    • async 返回的是一个Promise对象,await就是等待这个promise的返回结果后,再继续执行

    • await 等待的是一个Promise对象,后面必须跟一个Promise对象,但是不必写then(),直接就可以得到返回值

  • Object.values() 返回一个数组。

  • Object.entries() 返回一个键值对数组。

  • Object.getOwnPropertyDescriptors() 获取对象的描述符。

  • SharedArrayBuffer 对象用来表示一个二进制数据缓冲区。

ES9

ES10

ES11

  • 逻辑空赋值 ??= 仅在 ??= 左侧的值为 null 或者 undefined 时赋值。

    let user = { name: "admin" }
    ​
    user.name ??= "aaa";
    document.write(user.name)   // admin
    user.pwd ??= "123456";
    document.write(user.pwd)    // 123456
  • 可选链操作符?.)允许读取位于连接对象链深处的属性值,而不用明确验证链中的每个引用是否有效。

    可选链运算符允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 运算符的功能类似于 . 链式运算符,不同之处在于,在引用为空 (nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

    let user = {
        name: {
            firstName:"Bruce"
        },
        age: 20,
        /* func:function(){
             document.write("ff")
        } */
    }
    document.write(user.name?.firstName)    // name 属性存在,执行 name.firstName
    document.write(user.address?.home)      // address 属性不存在,不再往后执行,返回 undefined
    user.func?.();      //func方法存在即调用,不存在返回 undefined
  • Promise.allSettled 返回一个带有对象数组的 promise。

  • 新数据类型 BigInt 是一种数字类型的数据。

  • globalThis 全局属性 globalThis 包含全局的 this 值。

ES12

  • String.prototype.replaceAll() 返回一个新字符串。

  • Promise.any() 接收一个 Promise 可迭代对象,只用其中一个 promise 成功,就可以返回成功的 promise。

  • WeakRef 对象允许你保留另一个对象的弱引用,而不会阻止弱引用对象被 GC 回收。

  • 数字分隔符 可以在数字之间创建可视化的分隔符。

TypeScript

TypeScript 是一种由微软开发的自由和开源的编程语言,是一个拥有类型系统的 JavaScript 的超集,可以编译成纯 JavaScript。对于 TypeScript 这个单词的解释,有这么一种说法 TypeScript = Typed JavaScript。简言之,TypeScript = JavaScript+,会用JavaScript,也就会 TypeScript。

变量、常量

TypeScript 是一种强类型语言,量的声明可以强制标注类型。

const a:number = 1;
​
let name:string = 'libai';
let age:number = 23;
let b:boolean = true;
​
let nameArr:string[] = ["zhs","lisi","wsw"];
let nameArr:Array<string> = ["zhs","lisi","wsw"];           // 数组泛型
let nameArr:Array<string|number> = ["zhs","lisi","wsw"];    // 联合类型:多种类型数据
​
let stu:object = {name:'libai',age:23}
​
let a;  // 不指定类型,则默认 any 类型,与 JavaScript 无异,可以赋任意值

函数

  • 具名函数

function show(a:number){
    console.log(a)
}
​
function show2(a:number,b?:number){     // 可选参数
    console.log(a)
    // b 存在则计算 a + b
    if(b){
        console.log(a + b)
    }
}
​
function show3(a:number,b:number = 5){  // 默认值,不传b时,默认使用5
    console.log(a+b)
}
​
function show4(a:number,b:number):number{// 声明返回值类型
    return a + b;
}
  • 匿名函数

const show = function(a:number){
    console.log(a)
}
  • 箭头函数

// ES6
let sum = (a, b) => a + b;
​
// TypeScript: 指定参数类型和返回值
let sum = (a:number, b:number):number => a + b
let sum = (a:number, b:number = 5):number => a + b  // 默认值
let show = (msg):void => console.log(msg)           // 无返回值
  • 泛型函数

function getValue<T>(val:T):T{
    return val;
}
​
let val1 = getValue("abc");     //不指定类型,自动进行类型推断
let val2 = getValue<number>(2); // 指定类型

接口

接口可以用来约束对象、函数、以及类的结构和类型,是一种不能改变的代码协作契约。

interface Person{
    readonly id: string,    // 只读属性
    name: string,
    age: number,
    sex?: boolean           //可选属性
}
​
// 接口继承
interface User extends Person{
    address: string
}
    
let u : User = {
    id: '001',
    name: 'libai',
    age: 24,
    address:'中国'
}

类和继承

class Person{
    private name:string;        //private、protected、public、static(类名调用),同java
    age:number;
    readonly addr:string = "a"; // 类中的只读属性需初始化
    
    constructor(name:string, age:number){
        this.name = name;
        this.age = age;
    }
    
    show(){
        console.log(this.name)
    }
}
​
const stu2= new Person("libai",20);
stu2.show();
console.log(stu2.age)
​
// 继承
class Student extends Person{
    sex: string;
    constructor(name:string,age:number,sex:string){
        super(name,age);
        this.sex = sex;
    }
}

接口实现

interface Animal {
    head: number;
    name: string;
    eat(food: string): void; // eat 方法的描述
}
​
class Dog implements Animal{
    name: string;
    head: number;
    eat(food:string){
        console.log(food)
    }
    show(){}
}
​
let dog = new Dog();
dog.eat("食物")

原文地址:https://blog.csdn.net/qq_63843408/article/details/142863772

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!