前端复习(二)
ES6
2015 年发布的ECMAScript 2015,也叫 ECMAScript 6,简称为 ES6。
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
几种输出的方式 。
-
命名导出(每个模块包含任意数量)
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}
-
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"
-
默认导出(每个模块包含一个)
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. 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");
-
命名空间导入:导入全部
与导出模块的全部成员不同,在导入时,除了要与星号组合之外,还必须为其设置别名。这是由于加载的整个模块会被当成一个对象,而此对象需要一个名称,它的属性就是该模块所有的导出。
import * as user from './outer1.js'; console.log(user.name); user.setName("ddd");
-
默认导入:导入默认导出的值
//由于默认导出每个模块只有一个,所以导入时名字可以任意,下面的 name 也可以叫 a 或 abc 之类的。 import name from './outer5.js'; //当同时导入默认和非默认的导出值时,必须把默认的写在前面 import name,{pwd} from './outer5.js';
-
简洁导入:执行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依据其状态的变化,让异步操作变得有序,而Promise有三种互斥的状态,具体如下:
(1)pending:等待中,初始状态,此时还未处理(Promise中的)异步操作。
(2)fulfilled:已完成,异步操作成功时的状态。
(3)rejected:已拒绝,异步操作失败时的状态。
-
创建
如果要使用Promise,那么需要先初始化,可以通过构造函数的方式创建一个Promise实例,如下所示。
let promise = new Promise(function(resolve, reject) { /* executor */ });
构造函数
Promise()
能接收一个执行器(executor),即带有resolve
和reject
两个参数的函数。执行器会在构造函数返回新实例前被调用。它的两个参数也是函数,分别适合不同的语境,具体如下:(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()方法的两个参数,可分别指定状态变成fulfilled和rejected后的回调函数,而这两个回调函数的参数分别来自于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 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
-
异步迭代,await 可以和 for...of 循环一起使用,以串行的方式运行异步操作。
-
Promise.prototype.finally() 返回一个 Promise。
-
Rest/Spread 属性可展开字符串或者表达式。
ES10
-
Array.prototype.flat() 遍历数组中的所有元素(包括子数组)合并为一个新数组。
-
Array.prototype.flatMap() 用映射函数中的元素压缩成一个新数组。
-
String.trimStart() 用来去除字符串开头的空白字符。
-
String.prototype.matchAll 返回一个迭代器。
-
Symbol.prototype.description 返回 Symbol 对象的可选描述的字符串。
-
Object.fromEntries() 用于把键值对列表转换成一个对象。
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)!