ECMAScript新特性 & ES6

2015年开始ES保持每年一个版本的迭代

1、作用域:某个成员能够起作用的范围(目前有三种作用域:全局作用域、函数作用域、块级作用域)

2、const:只读的常量,声明的时候必须设置初始值,后续不可以修改

   最佳实践:不用var、主用const、配合let

3、数组的解构

  ...这种用法只能在解构的最后一个位置上使用
  成员个数小于解构个数,会按照从前到后的顺序去提取,多出来的成员不会被提取
  解构个数大于数组长度,会打印出undefined
      给解构成员加默认值:const { foo, bar, baz = 'baz default value' } = arr 如果未提取到数据会使用默认值

1 let arr = [1, 2, 3];
2 const { foo, bar, baz } = arr
3 console.log( foo, bar, baz ) // 1 2 3
4 let arr1 = [100, 200, 300]
5 const { foo1, ...rest } = arr1 
6 console.log( rest ) // [200, 300]

4、对象的解构

1 const obj = { name: "obz", age: 18 }
2 const { name } = obj
4 const name = 'tom'
5 const { name: objName = 'jake' } = obj 
/* 
如果名字冲突可以给解构的重新命名 对象中解构的某个名字:重新命名后的该值的名字

  如果需要给默认值可以接着在后面用=“默认值”: name: objName = 'jake'

 */ 
6 console.log( objName ) 

 5、模版字符串

  支持换行 可以写多行、差值表达式、

const name = 'tom'
const msg = `hey, ${ name } -- ${ 1+2 } --- ${Math.random()}`
console.log(msg)

6、带标签的模版字符串

  支持换行 可以写多行、差值表达式、

 1 const name = 'tom'
 2 const gender = true
 3 
 4 function myTagFunc (strings, name, gender ) {
 5     console.log( strings, name, gender  )
 6     // ['hey,' , 'is a ',  '.'] tom true
 7     const sex = gender ? 'man' : 'woman'
 8     return strings[0] + name + strings[1] + sex + strings[2]
 9 }
10 
11 const result  = myTagFunc(`hey, ${name } is a ${gender}.`)
12 console.log(result)
13      

7、字符串的扩展方法 

 1 const msg = 'Error: foo is not defined.'
 2 
 3 // startsWith 以xxx开始
 4 console.log( msg.startsWith('Error') )
 5 
 6 // endsWith 以xxx结束
 7 console.log( msg.endsWith('.') )
 8 
 9 // includes 是否包含xxx
10 console.log( msg.includes('foo') )

8、参数默认值

没有传递实际参数时,使用的值

 1 // 原来的
 2 function foo (enable) {
 3     enable = enable || true
 4     // 如果enable传递false时无法实现 须改为
 5     enable = enable == undefiled ? true : enable
 6     console.log(enable)
 7 }
 8 /*
 9 新写法: 如果为传入或者为undefiled时用默认值true
10 如果有多个参数时,带默认值的一定要在最后
11 */ 
12 function foo (a, enable = true) {
13     console.log(enable)
14 }

9、参数默认值

只能在行参的最后一位,只能出现一次

1  function foo(...args){
2    console.log(args) // [1, 2, 3, 4]  
3  }
4  foo(1, 2, 3, 4)
5 
6 // 展开数组
7 const arr = [ 'foo', 'bar', 'baz' ]
8 console.log(...arr) // foo  bar  baz

 

10、箭头函数

箭头左侧是传入的值,如果只有一个值可以省略()
箭头右侧是函数对应的方法,如果只有一个返回值可以省略return 和 { }
箭头函数不会改变this指向
在普通函数中,this始终会指向调用这个函数的对象
箭头函数当中没有this的机制,所以不会改变this的指向,也就是说在箭头函数的外面this是什么在里面拿到的this就是什么,任何情况下都不会发生改变

 1  function inc (number) {
 2    return  number + 1
 3  }
 4  const inc = n => n+1
 5  
 6  console.log(inc(100))
 7 
 8 const person = {
 9     name: 'tom',
10     sayHi: function() {
11         console.log(`hi, my name is ${ this.name }`) // hi, my name is  tom
12     }
13     sayHii: () => {
14         console.log(`hi, my name is ${ this.name }`) // hi, my name is  undefiled
15     }
16     sayHiAsync: function () {
17         //const _this = this
18         //setTimeout(function(){
19            //console.log(_this.name) // tom 
20         //}, 1000)
21         // 优化为
22         setTimeout(()=>{
23            console.log(_this.name) // tom 
24         }, 1000)
25     }
26 
27 }    

11、对象字面量的增强

为对象增加动态属性名,现在可以直接用[]使用动态的值
计算属性名: 表达式执行的结果作为属性名

 1 const bar = '123'
 2 
 3 const obj = {
 4     foo: 123,
 5     bar: bar // bar: bar => bar 等价
 6     bar,
 7     method: function () {}, // 省略 : function
 8     method () {},
 9     [Math.random()]: 123,
10     [1+1]: 345
11 }

12、对象扩展方法

Object.assign:讲多个源对象中的属性复制到一个目标对象中
从源对象中取,放到目标对象中

用后面对象中的属性,覆盖第一个对象,返回值是第一个对象

 1 const source1 = {
 2     a: 123,
 3     b: 123
 4 }
 5 const source2 = {
 6     b: 789,
 7     d: 789
 8 }
 9 const target = {
10     a: 456,
11     c: 456
12 }
13 const result = Object.assign(target, source1, source2)
14 console.log(target) // {a:123, c: 456, b: 789, d : 789 }
15 console.log(result === target) // true

Object.is 判断两个值是否相等

0 == false 两等比较前会进行数据转化
0 === false 三等是严格去对比两者是否相等,0和false类型不同,所以不相等
但是三等运算符无法比较+0 === -0  // true  NaN === NaN // false

Object.is(+0, -0) 
Object.is(NaN, NaN) 

 

 

13、Proxy
14、Proxy对比DefineProperty
15、Reflect
16、Promise

 


17、Set数据结构

 1 const s = new Set()
 2 s.add(1).add(2).add(3).add(2)
 3 console.log(s) // Set {1, 2, 3}
 4 
 5 s.forEach(i => console.log(i)) //  1 2 3
 6 
 7 for (let i of s) { console.log(i) } //  1 2 3
 8 
 9 console.log(s.size) // 3
10 
11 console.log(s.has(100)) // false
12 
13 console.log(s.delete(2)) // true
14 console.log(s) //  Set {1, 3}
15 
16 s.clear() 
17 console.log(s) //  Set {}
18 
19 // 为数组去重
20 const arr = [1,2,3,2,3,4,5];
21 const result = new Set(arr)
22 console.log(result) //  Set {1, 2, 3, 4, 5}
23 
24 // 如果想得到一个新的数组的话
25 const result1 = Array.from(new Set(arr))
26 const result2 = [...new Set(arr)]
27 console.log(result1, result2) // [1, 2, 3, 4, 5]

 

18、Map数据结构

可以用任意类型的值作为键

 1 const obj = {}
 2 obj[true] = 'value'
 3 obj[123] = 'value'
 4 obj[{a: 1}] = 'value'
 5 console.log(Object.keys(obj)) // ["123", "true", "[object Object]"]
 6 
 7 /*
 8 对象添加的键不是字符串,那内部就是将toString的结果当成这个键
 9 */
10 
11 const m = new Map()
12 const tom = {name: 'tom'}
13 m.set(tom, 90)
14 console.log(m) // Map { {name: tom => 90} }
15 console.log(m.get(tom)) // 90
16 m.has()
17 m.delete()
18 m.clear()
19 
20 m.forEach((value, key) => {
21     console.log(value, key)
22     // 90 {name: 'tom'}
23 })

19、Symbol

一种全新的原始数据类型
目前最主要的作用就是为对象添加独一无二的属性名

每次通过Symbol创建的都是唯一的值

 1 // shared.js =====
 2 const cache = {}
 3 
 4 // a.js =====
 5 cache['foo'] = Math.random()
 6 
 7 // b.js ====
 8 cache['foo'] = '123'
 9 
10 /*
11 多页面会造成冲突,之前会约定命名格式,但是如果不遵守约定也会出现重复覆盖的情况,所以可以通过Symbol来解决
12 */
13 const s = Symbol()
14 console.log(s) //  Symbol()
15 console.log( typeof s ) // symbol
16 console.log( Symbol() === Symbol() ) // false
17 console.log(Symbol('foo')) // Symbol(foo)
18 
19 const obj = {}
20 obj[Symbol()] = '123'
21 obj[Symbol()] = '456'
22 console.log(obj)
23 // { [Symbol()]: "123", [Symbol()]: "456"}
24 
25 const obj1 = {
26     [Symbol()]: '098'
27 }
28 
29 
30 // a.js ====
31 const name = Symbol()
32 const person = {
33     [name]: 'zxs',
34     say () { console.log(this[name]) }
35 }
36 
37 // b.js ====
38 person[Symbol()] // undefined 访问不到的
39 person.say() // zxs

const s1 = Symbol.for('foo')
const s2 = Symbol.for('foo')
console.log(s1 === s2) // true

20、for...of循环

 作为遍历所有数据结构的统一方式
可以循环可迭代的数据
ES中能够表示有结构的数据类型越来越多,为了给各种各样的数据结构提供统一的遍历方式,ES2015提供了Iterable接口
实现Iterable接口就是for...of循环的前提,只要数据结构实现了Iterable接口,就可以用for...of循环
原型对象中有Symbol(Symbol.iterator)的方法的才可以

 1 const arr = [100, 200, 300]
 2 
 3 for(const item of arr){
 4     console.log( item ) //  100 200 300
 5   if( item > 100 ){ break }   
 6   // 可以在for of中可以直接使用关键字break终止遍历   
 7 }
 8 
 9 const s = new Set(['foo', 'baz']);
10 for ( const item of s ){
11   console.log(item) // foo baz
12 }
13 
14 const m = new Map();
15 m.set('foo', '123')
16 m.set('bar', '345')
17 for( const item of m){
18     console.log(item)
19     // ['foo', '123']  ['bar', '345'] 把键和值放到数组中
20 }
21 for( const[key, value] of m){
22     console.log(key, value)
23     // foo 123    bar 345
24 }

21、ES2016 & ES2017

 1 1、Array.prototype.includes => 判断数组中是否存在某一项
 2 const arr = ['foo', 1, NaN, false]
 3 arr.includes(NaN) // true
 4 
 5 2、指数运算符
 6 console.log( Math.pow(2, 10) )
 7 console.log(2 ** 10)
 8 
 9 3、 Object.value: 打印对象中的值,放到一个数组中
10 let obj1 = { foo: 'value1', bar: 'values' }
11 Object.values(obj1);
12 ["value1", "values"]
13 
14 4、 Object.entries: 把对象转换成数据,key value为一维数组
15 [ ["foo", "value1"],  ["bar", "values"] ]
16 
17 for ( const [key, value] of Object.entries(obj1) ){ 
18     console.log(key, value) 
19 } 
20 
21 5、 String.prototype.padStart /  String.prototype.padEnd : 对齐数据长度 
22 用给定字符串填充目标字符串的开始或结尾位置,直到字符串达到指定长度为止
23 const books = { 
24   html: 5,
25   css: 16,
26   javascript: 128
27 }
28 
29 for ( const [name, count] of Object.entries(books) ){
30   console.log(`${ name.padEnd(16, '-') } | ${ count.toString().padStart(3, '0') }`)
31 
32   // html------------ | 005  css------------- | 016  javascript------ | 128
33 } 
34 
35 6、 在函数参数中添加结束尾逗号
36 优点:格式一致,重新排列比较方便;新建时只增加新增加的,少改动代码行数

 

posted @ 2021-02-25 18:37  *小七儿*  阅读(89)  评论(0编辑  收藏  举报