ES6 标准入门

let const命令

  1. 不存在变量提升,var 可以提升
  2. 暂时性死区(TDZ):在区块中存在let,const命令,这些区块在一开始就对这些命令声明的变量形成封闭作用域,只要在声明之前使用这些变量就会报错。在let const声明变量之前,该变量不能使用。
  3. 不允许重复声明

块级作用域

  1. 外层作用域无法调用块级作用域内部定义的变量,函数
  2. 内层作用域可以定义外层作用域 的同名变量

变量结构赋值

按一定模式,从数组和对象中提取值,对变量进行赋值
只要某种数据结构有Iterator接口,就可以使用数组形式的结构赋值
数组结构,变量的取值有元素的位置决定 对象没有次序,变量必须与属性同名,才能取到正确值

  1. 声明和赋值要在一句话中,不能拆开 let [a,b,c] = [1,2,3] √ let[ a,b,c] [a,b,c] = [1,2,3] ×
  2. 默认值[x =1, y=x] = [] // x=1,y=1
  3. 对象解构赋值 let{bar: aa} = {bar:‘sss’, foo:‘ddd’} aa // ‘sss’ 真正被赋值的不是模式bar 而是变量aa
  4. 字符串的解构赋值 const[a,b,c] = ‘edf’ a//‘e’ b//‘e’ c// 'f
  5. 函数参数的解构赋值 【[1,2], [3,4]】.map(([a,b]) => a+b) //[3,7]
    用途
    交换变量的值 【x, y】 = 【y, x】
    从函数中返回多个值 函数只能返回一个值,如果要返回多个值,只能放在数组中或对象中返回。let {a,b} = foo()
    提取json数据
    函数参数默认值

字符串的扩展

  1. 字符串的遍历接口 用for … of 循环遍历
  2. includes():返回boolean 表示是否找到了参数字符串
    startsWith():返回boolean, 表示参数字符串是否在源字符串的头部
    endsWith():返回boolean,表示参数字符串是否在元字符的尾部
    参数1:布标字符串 参数2:开始搜索的位置
  3. repeat():返回一个新字符串,表示将源字符串重复 n次
    若n是小数,则会取整
  4. padStart() padEnd() 在字符串头部/ 尾部补全字符串长度
    参数1:字符串最小长度, 参数2:用来补全的字符串 若省略,则用空格补全
    ‘cd’.padStart(5, ‘ad’) // ‘adacd’
  5. 模板字符串
    定义多行字符串,或者在字符串中镶嵌变量 变量写在${}中 ${}中可以写任意js代码,可以进行运算,引用对象属性,也可以调用函数
    所有空格 和缩进也会被保留在输出中

数值的扩展

  1. 0b / 0o 表示 二进制 / 八进制
  2. Number.isFinite(数字) 检查一个数值是否是非无穷 true/false 有穷/无穷
  3. Number.isNaN(数值) 检查一个数值是否是NaN
  4. Number.parseInt() 返回一个整数 参数2:返回的进制形式
  5. Number.parseFloat() 返回一个浮点数
    将parseInt() . parseFloat() 一直到Number对象上,行为完全不变
  6. Number.isInteger() 判断一个值是否是整数 JS 中 3.0 与3 被视为一个值
  7. 安全整数-2^53 - 2^53 之间
  8. Math对象的扩展
    Math.trunc() 去除一个数的小数部分,返回整数部分 对于非数值,先用Number将其转为数值
    Math.sign() 判断一个数值是 正数/负数/0 返回 +1/-1/0
    Math.cbrt() 计算一个数的立方根 开立方
    Math.hypot() 返回所有参数的平方和的平方根 勾股定理
  9. 指数运算符(**)
    2 ** 2 // 4
    a **= 3 => a= aaa

数组的扩展

  1. Array.from() 将类似数组的对象(有length属性)和可遍历(interator接口)的对象转化成真正的数组
    可以接受第二个参数,作用类似于数组的map方法,对每个元素进行处理,将处理后的值放入返回的数组
    Array.from(arr, x => x2) === Array.from(arr).map(x => x2)
  2. Array.of() 将一组值转换为数组
    弥补Array()的不足
    没有参数则返回空数组
    Array.of() //[]
    Array.of(2,8,9) // [2,8,9]
    Array.of(3) // [3]
    Array(3) // [ , , ]
  3. copyWithin() 在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原成员),然后返回当前数组。即 此方法会修改当前数组
  4. find() 找出第一个符合条件的数组成员 若没有找到返回-1
    [5,6,10,12].find(function(val, index, arr) {return val > 10} // 12
  5. findIndex() 返回第一个符合条件的数组成员的位置。若没有找到 返回-1
    [5,6,10,12].find(function(val, index, arr) {return val > 10} // 3
  6. fill() 用给定的数值填充数组
    [‘a’. ‘b’].fill(6) //[6, 6]
    参数1: 填充的值 参数2: 从哪里开始填充 参数3: 到此为止之前结束
  7. includes() 数组是否含有某值
    参数2: 搜索起始位置
    以此方式替代 indexOf()的查找
  8. 数组推导 直接通过现有数组根据一定条件生成新数组
    [for(i of[1,2,3]) i*2] //[2, 4, 6]
    for … of 在前 条件式在后 ,for… of 后面还可以加if条件句,设定循环限制条件

函数的扩展

  1. 允许设置默认值,直接写在参数定义后面 参数是默认声明的,不能在用let const再次声明
    默认参数 一般是尾参数
    制定了默认参数后,函数的length属性将会返回没有指定默认值的参数个数
  2. 作用域
let x = 1
function fn( y =x) {
	let x = 2
	alert( y )
}
fn()   // 1
函数调用时,y的默认值是变量x,此时x尚未在函数内部生成,所以想指向全局变量。 若全局变量不存在,则报错
  1. rest参数
    获取函数多余的参数。 rest参数只能是最后一个参数(尾参数)
    是数组 …rest=>[]

  2. 扩展运算符
    将一个数组转化为用逗号分隔的参数数列 …[1,2,3] => 1,2,3
    1. 合并分组:[…arr1, …arr2] === arr1.push(arr2)
    2. 函数返回值
    3. 字符串 转化为 数组 [ …‘abc’] // [‘a’, ‘b’, ‘c’]
    4. 任何类数组的对象都可通过 …转化为真正的数组 作用类似于Array.from()

  3. 箭头函数
    不可用于构造函数
    不可用于Generator函数
    没有自己的this, 其内部this就是外层代码块的this

  4. 尾调用
    函数最后一步调用的是另一个函数
    尾调用优化(严格模式下):若所有函数军事尾调用,则每次调用时只执行内层函数调用帧一次,大大节约内存
    只有不在调用外层函数的内部变量,才是真正的优化
    尾递归: 尾调用自身 节省没存 永远只存在一个调用帧
    递归: 本质上就是循环

  5. 柯里化: 将多参数的函数转换成但参数的形式

对象的扩展

  1. Object.assign() 将源对象的所有可枚举属性复制到目标对象。(不可枚举的 和 继承的属性不会被复制)
    参数参数1 :目标对象, 后面的参数是源对象
    若目标对象和源对象有同名属性,或多个源对象有同名属性,子后面的属性会覆盖前面的属性
    1. 为对象添加属性、方法
    2. 克隆对象 将原始对象赋值到一个空对象,得到原始对象的克隆 Object.assign({},originObject)
    3. 合并多个对象
    const merge = (…sources) => Object.assign({}, …sources)
  2. 属性遍历
    for … in 遍历对象自身的和继承的可枚举属性
    Object.keys( obj ) 返回一个数组,包含对象自身的(不含继承的)所有可枚举属性。
  3. 对象的扩展运算符
    rest参数 只能替代简单类型的值,是浅复制。
    合并 {…{x:1}, …{y: 2}} // {x: 1, y: 2}
    设置默认参数

Symbol

  1. ES6 新引入的原始数据类型 表示独一无二的值。是JS的第7种数据类型
  2. 不能使用new命令 因为Symbol不是对象,所以不能添加属性。
    let s = Symbol(‘foo’) 接受一个字符串作为参数,对Symbol实例进行描述,区分
  3. Symbol不能与其他类型的值进行运算
  4. 作为属性名的Symbol
    let a = {
    [mySymbol] : ‘aaa’
    }
    a[mySymbol] // ‘aaa’
    只能用括号,不能用点运算符
  5. 魔术字符串
    在代码中多次出现,与代码形成强耦合的某一个具体的字符串或数值。
    用变量代替 消除之
  6. Symbol属性名的遍历
    作为属性名, 该属性不会出现在 for …in for … of 中
    可以用Object.getOwnPropertySymbols 返回一个数组,含全部Symbol属性值
    Symbol.for() 和Symbol() 都会生成新的Symbol
    前者会现在全局查找给定的key是否存在,不存在再新建一个新的Symbol值
    Symbol。keyFor( ) 返回一个已经登记的Symbol类性值的key 即 Symbol.for() 生成的Symbol

Proxy

在目标前设置一更拦截,外界对该对象的访问都必须先通过这层拦截,可以对外界的访问进行过滤和改写
var proxy = new Proxy( target, 代理对象)
代理对象 = {
get: function (target, propKey) {…} 拦截某属性的读取操作
set: funciton (target, prop ,value) { … } 拦截某属性的赋值操作
apply: function( target, object, args) { … } 拦截 Proxy 实例作为函数调用的操作
construct: function( target, args, proxy) { … } 拦截Proxy实例作为构造函数的调用
}

Set

ES6 中的新的数据结构 类似于数组,但成员的值都是唯一的,没有重复的值
处理数组,去除数组的重复元素 …new Set(arr)
let s = new Set( )
[2, 2, 5, 6].map((x) => s.add(x)) // [2, 5, 6]

  1. 方法 :
    add(val) 添加某值,返回set结构本身。 S儿童内部判断两个值是否相同用的是 ===
    delete(val) 删除某值 返回Boolean 表述删除是否成功
    has(val) 判断是否拥有某值
    clear()清除所有成员 没有返回值
    .size Set成员的个数
  2. Array.from( ) 和 扩展运算符都可以将Set结构转化为真正的数组
    …new Set(【1, 2, 2, 3】) // [1, 2, 3]
  3. map filter forEach方法都可用于 Set
let a = new Set([1, 2, 3])
let b = new Set([2, 3, 4])
let union = new Set([...a, ...b]) // 并集
let intersect = new Set([...a].filter(x => b.has(x)) // 交集
let difference = new Set([...a].filter(x => !b.has(x)) // 差集

Map

JS的对象本质上是键值对的集合,但只能用字符串作为键。
es6提供了新的Map数据结构,类似于对象,也是键值对的集合,但键的范围不限于字符串,各种类型的值(包括对象)都可以当做键。
构造函数,可以接受数组为参数,该数组的成员是一个个表示键值对的数组。

let map = new Map( ['name' : 'zhangsan'], [' age': 18]]
map.get('name') // 'zahgnsan'
  1. 方法 :
    get(key) 查找key对应的值
    set(key, val) 设置key对应的值,返回整个Map结构。可以链式书写 map.set().set().set()
    delete(key) 删除某值 返回Boolean 表述删除是否成功
    has(key) 清除某个键
    clear()清除所有成员
    .size Map成员的个数
  2. 遍历
    map.keys() map.values() map.entries() forEach()
    扩展运算符 【…map】(并转换为数组)
    可以结合map filter 方法使用

Iterator

只要部署iterator接口(数组。类数组对象,Set,Map结构)就可以完成遍历操作,即一次处理该数据结构的所有成员。就可以用 for … of 遍历 就可以使用扩展运算符 将其转变为数组
字符串是类数组对象,所以可以使用扩展运算符转变为数组
iterator实际上是一个指针对象。
1. 不断地调用next方法
2. 第一次调用指针对象的next方法,将指着指向数据结构的第一个成员。返回一个对象,表示当前数据成员的信息,该 对象含有value, done,两个属性。value属性返回当前未知的成员;done属性是一个布尔值,表示遍历是否结束,即是否还有必要继续调用next方法
3. 当done返回false是 停止遍历

ES5原有的for … in 循环只能得到对象键名,不能只对接获得键值
ES6的for … of 循环 可以遍历得到键值 并结合break(), continue() return()跳出循环

Generator函数

生成Generator函数后,并不立即执行,而是等next() 调用
返回一个遍历器对象,可依次遍历Generator函数内部的每个状态
分段执行,next() 开始执行,yeild暂停执行
可以有多个yeild,但只能有一个return语句,可以生成多个值
也可以没有yeild,此时成了单纯的暂缓执行函数

  1. next(参数)
    第一次执行不需要参数,在Generator开始运行后继续想函数体内注入值,从而调整函数行为。
    改参数当成上一个yeild语句的返回值
  2. for… of 循环
    自动调用next() 方法, 一次返回yeild的值, 一遇见return就终止循环 不包括return返回值
functiion* num () {
	yeild 1
	yeild 2
	return 3
	yeild 4
}
for( let n of num() ) {
	console.log(n)
}
// 1, 2
// 不包括return返回值
  1. Generator嵌套
    在一个Generator钟执行另一个Generator函数
    yeild* 语句 等同于for … of
  2. Generator函数推导
    惰性求值,真正用的时候才会求职,保证效率
  3. Generator 与协程
    协程: 多线程(或单线程情况下的多个函数)并行执行,但只有一个线程处于正在执行的 状态,其他线程暂停。县城之间可以交换执行权。(同时存在多个栈,但只有一个栈是运行状态)
    子例程:堆栈式,子函数执行完毕后才能执行复函数(只有一个栈)

Promise 对象

本身是一个对象,用来传递异步操作的消息,代表了某件未来才会知道结果的事件
特点

  1. 对象状态不受外界影响,只有异步操作结构决定当前是哪一状态 任何其他操作都不能改变此状态
  2. 一旦状态改变就不会在发生变化,任何时候等可得到此结果
    缺点
  3. 无法仇晓Promise,一旦新建他就会立即执行,中途无法停止 、取消
  4. 若不设回调函数,Promise内部抛出的错误不会反映到外部
  5. 当处于pending状态是,无法得知目前进展到那一阶段(开始? 快结束?)
let promise = new Promise( function(resolve, reject) {
	......
	if ( 异步操作成功){
		resolve(value)
	} else {
		reject(err)
	}
}
promise.then( (value) => {
	console.log(value) // 调用操作成功的数据
	}, (err) => {
	console.log(err)  // 失败的返回
	}
}

1.then() 方法 两个参数
参数1: resolved返回的回调函数
参数2:reject返回的回调函数
then() 可以链式书写,依次执行两个回校函数,第一个回调完成后,将结果作为参数传入第二个回调函数中
2.catch()方法
处理 Promise跑出的错误
## 用catch() 代替 then(reject => { …})
catch(). then() 若没有报错 自会跳过catch() 继续执行then()
3.Promise.all([p1, p2, p3]}
p1, p2, p3 是 Promise的实例,他们的返回值构成一个数组
当p1, p2, p3 有一个rejected, 那么p的状态就变成rejected
4. Promise.race([p1, p2, p3])
p1, p2, p3任何一个先发生状态改变,p的状态就发生改变
5.Promise.resolve()
=== new Promise( resolve => resolve() )
若不带参数,返回一个Promise对象。
6. Promise.reject()
new Promise( rejected => rejected() )
7. done() 总是在回调连尾端,保证捕捉任何可能出现的错误
8. fianlly()不管Promise最后状态怎样都会执行的操作

异步操作

一个任务分成两段,先执行一段,转而执行其他任务,做好准备后再来执行第二段。(不连续的执行)
Generator函数
一个封装的异步任务,可以暂停/ 恢复执行
特点:函数体内外的数据交换和错误处理机制
next() 返回值value=>向外输出
next(参数) => 向内输入
部署错误处理代码
function* gen(){
try [ let y = yeild x + 2}
catch(e) { console.log(e)
return y
}
gen().throw() //报错 并被try…catch 捕捉
函数的求值策略
传名调用:只在执行时求值
传值调用:先求值在带入函数中
Thunk函数
编译器传名调用先将参数放在一个临时函数中,再将临时函数传入函数体,此临时函数就是thunk函数
JS 中的 Thunk函数
JS用的是传值调用,Thunk将多参数函数转换为单参数函数,且只接受回调函数为参数

async函数

var asyncFn = async function ( ) {
var fi = await readFile(’/test.exe’)
}
async shi Generator函数的语法糖, 用await 替换yield async替代*
1.内置执行器,不需要外部调用next() asyncFn () 就可以得到结果
2. 返回值是Promise对象,可用then() 指定下一步操作

class

本身是构造函数,类的所有方法都定义在类的prototype上
实例对象: 实例对象的属性 除了显示定义在其本身上(this),其他的定义在原型(class)上
不存在变量提升 只有先写类,在实例化

class Foo{
	constructor(x, y) {
		this.x = x,
		this.y = y
	}
	someMethods(){
		console.log(this.x + this.y)
	}
}
let foo = new Foo()
foo(2, 3)

继承

class newPoint extends Foo{ 
		constructor(x, y, c) {
			super(x, y) //调用父类的constructor(x, y)
			this.c = c
		}
		someMethods(){
			*super.someMethods //调用父类的方法*
	}
 }
**在子类构造函数中,必须先调用super后才能使用this关键字**
   因为子类实例的构建是基于对父类实例的加工,只有super才能返回弗雷实例,
   所以必须在constructor中先调用super在使用this
 
 1. 子类的__proto__ 属性指向父类
 2. 子类的prototype 属性的__proto__ 指向父类的prototype属性
 3. 子类实例的__proto__ .__proto__ 指向父类的__proto__ 

class的取值函数(getter)和存值函数(setter)
相同的名字

class Foo{
	constructor(x, y) {
		this.x = x,
		this.y = y
	}
	get **someval**(){
		return this.x
	}
	set **someval** (val) {
		this.x = val
}
  1. class的静态方法
    类相当于实例的原型,若在类的方法前加上 static 则该方法不会被实例继承,而只能由类直接调用
    父类的静态方法可以被子类继承
    静态方法可以从super上调用
  2. class的静态属性
    class自身的属性 而不是定义在实例对象(this)的属性
    在class外部设置 因为class内只有静态方法,没有静态属性
    class Foo {。。。}
    Foo.x = 1

猜你喜欢

转载自blog.csdn.net/weixin_42372054/article/details/82937169