ES6新增
- let、const、块级作用域、箭头函数、模板字符串、BigInt,Symbol数据类型
- 解构赋值(数组、对象)
- 字符串新增方法
- 数组新增方法(扩展运算符)
- 对象新增方法
- 新的数据结构Set 和 Map
- Proxy
- Promise
- async和await
let、const、块级作用域
-
let声明的变量没有变量提升,必须先声明后使用;
-
暂时性死区。let声明的变量只能在当前块级作用域内使用
-
let不允许在同一作用域重复声明同一个变量;
-
const声明常量,声明就必须赋值,切不能修改;
-
块级作用域内可以声明函数,但是类似var会将函数声明提升到块级作用域的头部;
-
JavaScript 大于16 位的整数是无法精确表示的,不适合进行科学和金融方面的精确计算。二是大于或等于2的1024次方的数值,JavaScript 无法表示,会返回
Infinity
。BigInt(123) // 123n //后边加n
-
Symbol一种新的原始数据类型,表示独一无二的值。可用于对象的属性,防止属性名的冲突
let s = Symbol(); typeof s // "symbol" let a = { [s]: 'Hello!' };
箭头函数
(argument1, argument2, … argumentN) => {
// function body
}
括号内的是参数列表,后跟“胖箭头”(=>),最后是函数体。
-
非常简洁的语法,省略 function 关键字;
如果函数体是单个表达式,则可以不使用花括号并将其置于内联中(省略大括号直接将表达式写在一行中)。 表达式的结果将由函数返回。 const add = (a, b) => a + b; 如果只有一个参数,你甚至可以省略参数的括号 const getFirst = array => array[0];
-
this指向的是定义时所在的对象(跟着爹走);Call,apply,bind不能够改变箭头函数的this指向;
-
箭头函数中没有prototype原型
-
箭头函数没有constrcutor没有构造器
-
不能够使用new进行实例化
-
箭头函数中不能够使用arguments对象,用剩余参数来代替;
使用场景
- 数组的循环,不改变this的指向;
- promise的then方法传入成功的回调
- vuex中mapState引入state中一些data
不适用场景:
- 定义对象方法
对象的方法中this指向调用这个方法的对象
let obj = {
a:1,
b(){
console.log(this.a) }
}
obj.b() //1 this指向obj,所以可以获取到对象的属性a
若b换成箭头函数,则this就指向window,获取不到对象的属性
- 定义原型方法 :使用构造函数,this也是指向window
- 定义构造函数
定义构造函数是不允许使用箭头函数的,系统会抛出异常
-
定义事件回调函数。
绑定点击事件回调中this也是指向window
解构赋值(数组、对象)
let [a, b, c] = [1, 2, 3]; //数组的结构
let [foo = true] = []; //设置默认值
let {
foo, bar } = {
foo: 'aaa', bar: 'bbb' };
let {
foo: baz } = {
foo: 'aaa', bar: 'bbb' }; //别名
字符串新增方法
-
for … of… 循环
-
模板字符串
${变量}
-
//第二个参数,表示开始搜索的位置(位置就是索引) let s = 'Hello world!'; s.startsWith('world', 6) // true startWith从第n个位置开始直到结束 s.endsWith('Hello', 5) // true endsWith针对前n个字符 s.includes('Hello', 6) // false includes从第n个位置开始直到结束 'hello'.repeat(2) // "hellohello" //字符串重复n次,n=0则为空字符串 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' const s = ' abc '; s.trim() // "abc" 消除前后空格 s.trimStart() // "abc " 消除前空格 s.trimEnd() // " abc" 消除后空格 'aabbcc'.replaceAll('b', '_') 2021年参数可以为字符串,也可以全局正则(/b/g)
数组新增方法(扩展运算符)
-
扩展运算符:将数组转为参数序列
console.log(...[1, 2, 3])// 1 2 3 可用于合并数组
-
Array.from()将类似数组的对象转为数组
Array.of()
方法用于将一组值,转换为数组let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; let arr2 = Array.from(arrayLike); // ['a', 'b', 'c'] Array.of(3, 11, 8) // [3,11,8]
-
数组实例的 find() 和 findIndex()
[1, 4, -5, 10].find((n) => n < 0) // -5 第一个符合条件的数组成员 [1, 4, -5, 10].findIndex((n) => n < 0) // 2 第一个符合条件的数组成员的索引
-
includes()
-
对象的新增方法
-
Object.is()
比较两个值是否严格相等+0 === -0 //true NaN === NaN // false Object.is(+0, -0) // false Object.is(NaN, NaN) // true
-
Object.assign()
对象的合并 -
Object.setPrototypeOf(object, prototype)和Object.getPrototypeOf() 读取或设置当前对象的原型对象
let a = { x:1} Object.setPrototypeOf(a, { y:2}) console.log(a.y) //2 Object.getPrototypeOf(a) //{y: 2}
-
Object.keys(),Object.values(),Object.entries(),Object.fromEntries()
var obj = { foo: 'bar', baz: 42 }; Object.keys(obj) // ["foo", "baz"] Object.values(obj) // ["bar", 42] Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ] Object.fromEntries([ ['foo', 'bar'], ['baz', 42]]) // { foo: "bar", baz: 42 }
新的数据结构Set 和 Map
-
Set类似于数组,但是成员的值都是唯一的,没有重复的值。
-
Set的属性size(长度);
-
Size的方法:add()、delete()、has()、clear()
// 数组去重 [...new Set(array)] let s = new Set([1,2]); //let s = new Set() s.add(3) //Set(3) {1, 2, 3} Array.from(s) //[1,2,3] 转换为数组 s.delete(1) //true 删除成功 s.has(1) //false s.clear() //全部清空 Set(0) {} s.size //0
-
Map 数据结构。它类似于对象,也是键值对的集合
const map = new Map([ ['name', '张三'], ['title', 'Author'] ]); //Map(2) {"name" => "张三", "title" => "Author"} //原型方法 map.size // 2 map.has('name') // true是否有属性 map.get('name') // "张三" 读取属性 map.set("age", 18) //设置属性 map.delete('name') //删除属性 map.clear() //清除所有属性 [...map.keys()] //["name", "title", "age"] [...map.values()] // ["组件", "Author", 18] [...map.entries()] //[["name", "组件"],["title", "Author"]]
-
Set和Map都可以使用for…of循环
Proxy
-
在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写
var proxy = new Proxy(target, handler); //参数:目标对象和处理器handler var proxy = new Proxy({ }, { get: function(target, propKey) { return 35; } }); let obj = Object.create(proxy); obj.time // 35
-
处理器拦截操作有:13种
- get(target, propKey, receiver) 拦截对象属性的读取,比如proxy.foo
- set(target, propKey, value, receiver):拦截对象属性的设置,比如
proxy.foo = v
- has(target, propKey):拦截
propKey in proxy
的操作,返回一个布尔值 - deleteProperty(target, propKey):拦截
delete proxy[propKey]
的操作,返回一个布尔值
promise
-
Promise 是异步编程的一种解决方案。回调地狱:异步请求套异步请求,所以可以使用promise
-
异步:定时器、ajax、事件处理(点击事件等)、nodejs读取文件
-
Promise
对象有以下两个特点-
Promise的三个状态:
pending
(进行中)、fulfilled
(已成功)和rejected
(已失败) -
状态不受外界影响,只取决于异步操作的结果。
-
一旦状态改变,就不会再变,任何时候都可以得到这个结果,从
pending
变为fulfilled
和从pending
变为rejected
-
-
Promise原型对象的方法(实例也可以调用):then() 、catch()、finally()
-
Promise的Api:
- Promise.all([p1,p2,p3],()=>{ }) //全部成功才成功,有一个失败就失败
- Promise.race([p1,p2,p3],()=>{}) //只要一个执行完成即可执行回调,最先执行完的状态
- Promise.allSettled() 所有执行完,状态只会是失败
- Promise.any() 只要一个成功就成功
- Promise.resolve() 将现有对象转为 Promise 对象
- Promise.reject(reason) 返回一个新的 Promise 实例,该实例的状态为
rejected
- Promise.try() 和Promise.catch()不管是否包含异步操作,都用
then
方法指定下一步流程,用catch
方法处理f
抛出的错误。Promise.try
就是模拟try
代码块,就像promise.catch
模拟的是catch
代码块。捕获所有同步和异步的错误。
//axios就是将ajax使用promise封装的 function axios(){ p = new Promise((resolve,reject)=>{ $.ajax({ url:'', success(){ resolve(1) }, fail(){ reject(2) } }) }) return p } axios().then((data)=>{ console.log(data) //1 }).catch(data=>{ console.log(data) //2 }) //若使用async和await async fn()=>{ let data = await axios() console.log(data) }
async和await
async和await将异步方法定义为同步,原理就是generate+yield(暂停),执行next()得到暂停的值的语法糖;
Generator
- Generator 函数是 ES6 提供的一种异步编程解决方案。
- Generator 函数是一个普通函数,但是有两个特征。一是,
function
关键字与函数名之间有一个星号;二是,函数体内部使用yield
表达式,定义不同的内部状态 - Generator 函数是分段执行的,
yield
表达式是暂停执行的标记,而next
方法可以恢复执行 - 每次调用遍历器对象的
next
方法,就会返回一个有着value
和done
两个属性的对象。value
属性表示当前的内部状态的值,是yield
表达式后面那个表达式的值;done
属性是一个布尔值,表示是否遍历结束
class
构造函数的定义和调用
// function Person (){
// this.name='建林'
// this.age=18
// this.say=function(){
// console.log('say方法')
// }
// }
new一个构造函数的实例即可调用属性和方法
//class的定义和使用
class Person {
constructor(){
//里边方属性
this.name='建林'
this.age=18
}
say() {
console.log('say方法')
}
}
class Teacher extends Person {
//extends继承父类的属性和方法
//复杂写法
constructor(){
super();// 继承必须写super 他就是父类 上面的那个 constructor
this.score = 100
this.name='思聪'
}
//简单写法,不需要this
score = 100
name='思聪'
eat(){
console.log('eat')
}
}
//调用
let t1=new Teacher()
console.log(t1.name) //思聪
遍历器(Iterator)
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for...of
循环,Iterator 接口主要供for...of
消费。
Iterator 的遍历过程是这样的。
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
(2)第一次调用指针对象的next
方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的next
方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的next
方法,直到它指向数据结构的结束位置。
每一次调用next
方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value
和done
两个属性的对象。其中,value
属性是当前成员的值,done
属性是一个布尔值,表示遍历是否结束。
下面是一个模拟next
方法返回值的例子。
var it = makeIterator(['a', 'b']);
it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{
value: array[nextIndex++], done: false} :
{
value: undefined, done: true};
}
};
}
TypeScript
JavaScript的超集,有更严格的类型要求
let num:number = 99
function add(x:number,y:number):number{
return x+y //参数x和y都必须是number类型,且返回值也是number类型
}
ES6装饰器decorator
-
装饰器是一个函数,修饰类class
-
在类或类的属性方法名之前写@函数名,实现一些代码的复用
//装饰器是一个函数,给类或其方法加上一些其他的属性或者其他逻辑 function test(target){ target.name = '张三' console.log(‘类调用了’) }