ECMAScript新特性

一、内容概要

  • ECMAScript 与 JavaScript
  • ECMAScript 的发展过程
  • ECMAScript 2015的新特性
  • And more…

二、ECMAScript 概述

  1. JavaScript 是在 ECMAScript 的基础上扩展的语言。

  2. JavaScript @ web端:ECMAScript和WebAPI(DOM、BOM)组成

  3. JavaScript @ node.js端:ECMAScript和 Node APIs (fs、net、etc)组成

三、ECMAScript 2015 (ES6)

1.ES6学习概要

  1. 解决原有语法上的一些问题或者不足
  2. 对原有语法进行增强
  3. 全新的对象、全新的方法、全新的功能
  4. 全新的数据类型和数据结构

2.准备工作(学习环境)

  1. 运行环境 : node(用) 和浏览器都行

  2. 自动监听 node 运行,用 nodemon 包:

    /* 命令行输入*/
    npm init  				// 初始化
    npm install -g nodemon	// 安装包
    nodemon index.js 		// 启动项目
    

3.ES2015 let 和 块级作用域

作用域

  1. 全局作用域
  2. 函数作用域
  3. 块级作用域(es2015 新增)
    1. var 声明的变量会产生作用域提升。
    2. let 关键字声明的变量不会提升,必须先声明才能用,否则报错:引用异常

4.ES2015 const 关键词

  1. const 是用来定义 JavaScript 的常量(恒量)的。

  2. const 只是在 let 的基础上多了个只读的特性。

  3. const 只有在声明的同时赋值,否则会报错。

    const obj = {};
    obj.name = 'linxing';		// 不会报错,因为没有改变obj的引用地址,只是增加了obj的属性
    obj = {};					// 错误,修改了obj的引用值
    
  4. 最佳实践:不用 var , 主用 const,变量需要改变才用 let

5.ES2015 数组的解构

const arr = [100, 200, 300]

/* 不用解构的做法 */
// const foo = arr[0]
// const bar = arr[1]
// const baz = arr[2]
// console.log(foo, bar, baz)		// 100 200 300

/*解构的做法*/
// const [foo, bar, baz] = arr
// console.log(foo, bar, baz)		// 100 200 300

// const [, , baz] = arr			// 不需要的参数可以用 , 分开
// console.log(baz)					// 300

// const [foo, ...rest] = arr		// 可以用 ...的语法获取剩余参数(只能放在最后面)
// console.log(rest)				// [ 200, 300 ]

// const [foo, bar, baz, more] = arr // 当左边参数多于右边 多余的变成 undefined
// console.log(more)				// undefined

// const [foo, bar, baz = 123, more = 'default value'] = arr	// 给默认参数
// console.log(bar, more)			// 200  default value

/*示例*/
const path = '/foo/bar/baz'
// const tmp = path.split('/')
// const rootdir = tmp[1]

const [, rootdir] = path.split('/')
console.log(rootdir)

5.ES2015 对象的解构

  1. 对象的解构采用的是 属性匹配

    const obj = { name: 'zce', age: 18 }
    const { name } = obj
    console.log(name)				// 'zce'
    
  2. 对象的解构重命名

    const obj = { name: 'zce', age: 18 }
    const name = 'tom'
    const { name: objName } = obj
    console.log(objName)			// 'zce'
    
  3. 对象的解构重命名+给默认值

    const { log } = console;
    const obj = { name: 'zce', age: 18 }
    const name = 'tom'
    const { name: objName = 'linxing' } = obj
    log(objName)			// 'zce'
    

6.ES2015 字符串模板(``)

  1. 字符串模板中间可以使用 ${变量名} 包裹变量

  2. 示例

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

7.ES2015 带标签的模板字符串(``)

  1. 模板字符串的标签就是一个特殊的函数,用来重新渲染处理模板引擎。

  2. 使用这个标签就是调用这个函数

    const name = 'tom'
    const gender = false
    
    function myTagFunc (strings, name, gender) {
      // strings 是个以 ${} 切割的数组
      // console.log(strings, name, gender)       
      // return '123'
      const sex = gender ? 'man' : 'woman'			
      return strings[0] + name + strings[1] + sex + strings[2]
    }
    
    const result = myTagFunc`hey, ${name} is a ${gender}.`
    
    console.log(result)
    

8.ES2015 字符串的扩展语法

  1. str.startsWith(params ) : 查找字符串中的开头是否以 params 开头,返回 boolean 类型。

  2. str.endsWith(params ) : 查找字符串中的结尾是否以 params 开头,返回 boolean 类型。

  3. str.includes(params ) : 查找字符串中是否包含 params ,返回 boolean 类型。

    const message = 'Error: foo is not defined.'
    console.log(
      // message.startsWith('Error')		// true
      // message.endsWith('.')				// true
      message.includes('foo')				// true
    )
    

9.ES2015 参数的默认值

  1. es2015 之前使用短路 (||)的方式设置默认参数,这是错误的做法

    function foo (enable) {
      // 短路运算很多情况下是不适合判断默认参数的,例如 0 '' false null
      // enable = enable || true
      enable = enable === undefined ? true : enable
      console.log('foo invoked - enable: ')
      console.log(enable)
    }
    foo(false)
    
  2. 默认参数一定是在形参列表的最后

    function foo (enable = true) {
      console.log('foo invoked - enable: ')
      console.log(enable)
    }
    
    foo(false)
    

10.ES2015 剩余参数

  1. es2015 之前是使用 arguments 的伪数组去接受参数。

  2. es2015 中使用 … 去接受 ,但是参数有多个的时候需要放在最后面

    function foo (first, ...args) {
      console.log(args)
    }
    foo(1, 2, 3, 4)
    

11.ES2015 展开数组

const arr = ['foo', 'bar', 'baz']

// console.log(							// 原始方法
//   arr[0],
//   arr[1],
//   arr[2],
// )

// console.log.apply(console, arr)		// es2015 之前的方法

console.log(...arr)						// ...方式

12.ES2015 箭头函数

  1. 使用箭头函数 能使代码更加简单易读。

    const inc = n => n + 1
    console.log(inc(100))		// 101
    

13.ES2015 箭头函数和this指向

const person = {
  name: 'tom',
  // sayHi: function () {
  //   console.log(`hi, my name is ${this.name}`)
  // }
  sayHi: () => {
    console.log(`hi, my name is ${this.name}`)		// hi, my name is undefined
  },
  sayHiAsync: function () {
    // const _this = this							// 用变量保存起来
    // setTimeout(function () {
    //   console.log(_this.name)
    // }, 1000)

    console.log(this)
    setTimeout(() => {
      // console.log(this.name)
      console.log(this)
    }, 1000)
  }
}
person.sayHiAsync()

14.ES1025 对象字面量的语法增强

const bar = '345'

const obj = {
  foo: 123,
  // bar: bar
  // 属性名与变量名相同,可以省略 : bar
  bar,
  // method1: function () {
  //   console.log('method111')
  // }
  // 方法可以省略 : function
  method1 () {
    console.log('method111')
    // 这种方法就是普通的函数,同样影响 this 指向。
    console.log(this)
  },
  // Math.random(): 123 // 不允许
  // 通过 [] 让表达式的结果作为属性名
  [bar]: 123
}

// obj[Math.random()] = 123

console.log(obj)
obj.method1()

15.ES2015 Object.assign()

  1. object.assig()方法是把源对象里的属性来赋给目标对象。(有则覆盖,没有则添加)。

    const source1 = {
      a: 123,
      b: 123
    }
    
    const source2 = {
      b: 789,
      d: 789
    }
    
    const target = {
      a: 456,
      c: 456
    }
    
    const result = Object.assign(target, source1, source2) // target为目标对象,其他的源对象  
    
    console.log(target)				// { a: 123, c: 456, b: 789, d: 789 }
    console.log(result === target)	// true
    
  2. 应用场景

    function func (obj) {
      // obj.name = 'func obj'
      // console.log(obj)
    
      const funcObj = Object.assign({}, obj)
      funcObj.name = 'func obj'
      console.log(funcObj)
    }
    
    const obj = { name: 'global obj' }
    
    func(obj)
    console.log(obj)
    

16.ES2015 Object.is()

console.log(
  // 0 == false              // => true
  // 0 === false             // => false
  // +0 === -0               // => true
  // NaN === NaN             // => false
  // Object.is(+0, -0)       // => false
  // Object.is(NaN, NaN)     // => true
)

17.ES2015 Proxy

  1. 这是vue.3 开始用 proxy 处理响应数据,vue3以前使用的是Object.defineProperty()方法响应数据。

  2. const person = {
      name: 'zce',
      age: 20
    }
    
    const personProxy = new Proxy(person, {
      // 监视属性读取
      get (target, property) {
        return property in target ? target[property] : 'default'
        // console.log(target, property)
        // return 100
      },
      // 监视属性设置
      set (target, property, value) {
        if (property === 'age') {
          if (!Number.isInteger(value)) {
            throw new TypeError(`${value} is not an int`)
          }
        }
    
        target[property] = value
        // console.log(target, property, value)
      }
    })
     personProxy.age = 100
     personProxy.gender = true
    

18.ES2015 Proxy 对比 Object.defineProperty() 方法

  1. Proxy 是以非入侵的方式监管了对象的读写

    const person = {}
    
    Object.defineProperty(person, 'name', {
      get () {
        console.log('name 被访问')
        return person._name
      },
      set (value) {
        console.log('name 被设置')
        person._name = value
      }
    })
    Object.defineProperty(person, 'age', {
      get () {
        console.log('age 被访问')
        return person._age
      },
      set (value) {
        console.log('age 被设置')
        person._age = value
      }
    })
    
    person.name = 'jack'
    
    console.log(person.name)
    
    
  2. Proxy 比 Object.defineProperty() 更加强大,可以直接监听数组,而不需要对数组进行额外操作。

    const list = []
    
    const listProxy = new Proxy(list, {
      set (target, property, value) {
        console.log('set', property, value)
        target[property] = value
        return true // 表示设置成功
      }
    })
    
    listProxy.push(100)
    listProxy.push(100)
    
    
  3. Proxy 可以监视读写以外的操作

    const person = {
      name: 'zce',
      age: 20
    }
    
    const personProxy = new Proxy(person, {
      deleteProperty (target, property) {
        console.log('delete', property)
        delete target[property]
      }
    })
    
    delete personProxy.age
    console.log(person)
    
  4. Proxy 方式更为合理

    const person2 = {
      name: 'zce',
      age: 20
    }
    
    const personProxy = new Proxy(person2, {
      get (target, property) {
        console.log('get', property)
        return target[property]
      },
      set (target, property, value) {
        console.log('set', property, value)
        target[property] = value
      }
    })
    
    personProxy.name = 'jack'
    
    console.log(personProxy.name)
    

19.ES2015 Reflect方法

  1. Reflect 内部封装了一系列对对象的底层操作
const obj = {
  name: 'zce',
  age: 18
}

// console.log('name' in obj)
// console.log(delete obj['age'])
// console.log(Object.keys(obj))

console.log(Reflect.has(obj, 'name'))
console.log(Reflect.deleteProperty(obj, 'age'))
console.log(Reflect.ownKeys(obj))

20.ES2015 Promise

21.ES2015 Class类

class Person {
  constructor (name) {
    this.name = name
  }

  say () {
    console.log(`hi, my name is ${this.name}`)
  }
}

const p = new Person('tom')
p.say()

22.ES2015 Class 类的静态方法

class Person {
  constructor (name) {
    this.name = name
  }

  say () {
    console.log(`hi, my name is ${this.name}`)
  }

  static create (name) {
    return new Person(name)
  }
}

const tom = Person.create('tom')
tom.say()

23.ES2015 Class 类的继承(extends super())

class Person {
  constructor (name) {
    this.name = name
  }

  say () {
    console.log(`hi, my name is ${this.name}`)
  }
}

class Student extends Person {
  constructor (name, number) {
    super(name) // 父类构造函数
    this.number = number
  }

  hello () {
    super.say() // 调用父类成员
    console.log(`my school number is ${this.number}`)
  }
}

const s = new Student('jack', '100')
s.hello()

24.Set()数据解构

  1. 确保存储在 Set 数据结构的唯一性。

    1. 添加方法:setData.add (params)
    2. 删除方法:setData.delete(params)
    3. 查找方法:setData.has(parsms)
    4. 清除方法:setData.clear()
    const s = new Set()
    
    s.add(1).add(2).add(3).add(4).add(2)
    console.log(s)
    s.forEach(i => console.log(i))
    for (let i of s) {
      console.log(i)
    }
    console.log(s.size)
    console.log(s.has(100))
    console.log(s.delete(3))
    console.log(s)
    s.clear()
    console.log(s)
    
  2. 经常用来给数组去重

    const arr = [1, 2, 1, 3, 4, 1]
    
    // const result = Array.from(new Set(arr))
    const result = [...new Set(arr)]
    
    console.log(result)
    

25.ES2015 Map()数据结构

  1. 可以运用任意类型的值作为键
  2. 键 =》值
const m = new Map()
const tom = { name: 'tom' }
m.set(tom, 90)
console.log(m)
console.log(m.get(tom))
// m.has()
// m.delete()
// m.clear()
m.forEach((value, key) => {
  console.log(value, key)
})

26.ES2015 Symbol()数据结构

  1. 扩展对象,属性名冲突问题
  2. 两个 Symbol 永远不会相等
  3. 使用 Symbol 为对象添加用不重复的键
  4. Symbol 模拟实现私有成员
  5. 最主要功能就是为对象添加独一无二的属性名
const name = Symbol()
const person = {
  [name]: 'zce',
  say () {
    console.log(this[name])
  }
}

27.ES2015 for…fo循环

const arr = [100, 200, 300, 400]
for (const item of arr) {
  console.log(item)			// 100 200 300 400
  if (item > 100) {
    break
  }
}

28.ES2015 实现可迭代接口

const set = new Set(['foo', 'bar', 'baz'])

const iterator = set[Symbol.iterator]()

// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())

while (true) {
  const current = iterator.next()
  if (current.done) {
    break // 迭代已经结束了,没必要继续了
  }
  console.log(current.value)
}

29.迭代器模式

const todos = {
  life: ['吃饭', '睡觉', '打豆豆'],
  learn: ['语文', '数学', '外语'],
  work: ['喝茶'],

  // 提供统一遍历访问接口
  each: function (callback) {
    const all = [].concat(this.life, this.learn, this.work)
    for (const item of all) {
      callback(item)
    }
  },

  // 提供迭代器(ES2015 统一遍历访问接口)
  [Symbol.iterator]: function () {
    const all = [...this.life, ...this.learn, ...this.work]
    let index = 0
    return {
      next: function () {
        return {
          value: all[index],
          done: index++ >= all.length
        }
      }
    }
  }
}

todos.each(function (item) {
  console.log(item)
})

console.log('-------------------------------')

for (const item of todos) {
  console.log(item)
}

29.ES2015 生成器函数(Generator)

  1. 通过在函数的前面加个* 生成一个生成器函数的函数体,函数体会执行直到遇到 yield 停止执行。等再次调用.next() 再往下执行。
// function * foo () {
//   console.log('zce')
//   return 100
// }

// const result = foo()
// console.log(result.next())

function * foo () {
  console.log('1111')
  yield 100
  console.log('2222')
  yield 200
  console.log('3333')
  yield 300
}

const generator = foo()

console.log(generator.next()) // 第一次调用,函数体开始执行,遇到第一个 yield 暂停
console.log(generator.next()) // 第二次调用,从暂停位置继续,直到遇到下一个 yield 再次暂停
console.log(generator.next()) // 。。。
console.log(generator.next()) // 第四次调用,已经没有需要执行的内容了,所以直接得到 undefined

29.ES2015 生成器应用

function * createIdMaker () {
  let id = 1
  while (true) {
    yield id++
  }
}

const idMaker = createIdMaker()

console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)

// 案例2:使用 Generator 函数实现 iterator 方法

const todos = {
  life: ['吃饭', '睡觉', '打豆豆'],
  learn: ['语文', '数学', '外语'],
  work: ['喝茶'],
  [Symbol.iterator]: function * () {
    const all = [...this.life, ...this.learn, ...this.work]
    for (const item of all) {
      yield item
    }
  }
}

for (const item of todos) {
  console.log(item)
}

四、ESMAScript 2016(ES7)

1.数组的includes 方法

  1. Array.property.includes 方法

    const arr = ['foo', 1, NaN, false]
    console.log(arr.includes('foo'))  // 返回 Boolean 可以查找NaN
    

2.指数运算符

console.log(Math.pow(2, 10))
console.log(2 ** 10)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值