ES6新特性

  • ECMAScript 与 Javascript

  • ECMAScript的发展过程

  • ECMAScript2015的新特性

  • And more…

  • ECMAScript (ES) 通常看作Javascript的标准化规范 实际上JavaScript是ECMAScript的扩展语言

    • ECMAScript只提供了最基本的语法
    • JavaScript @ Web (在浏览器环境中): JavaScript = ECMAScript + Web APIs(DOM + BOM)
    • JavaScript @ Nodejs (在浏览器环境中): JavaScript = ECMAScript + Node APIs(fs + net + etc.)
    • Javascript语言本身是ECMAScript

ES6

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

let与块级作用域

  • 作用域 - 某个成员能够起作用的范围
  • 全局作用域 函数作用域 块级作用域
  • 块 : 代码中花括号包裹起来的范围
  • let没有声明提升
// 块
// if(true){
//     // var foo = 'foo'
//     let foo = 'foo'
//     console.log(foo)
// }
// // console.log(foo)

// ----------------------------------------------------
// for循环中的计数器
// for(var i = 0; i < 3; i++){
//     for(var i = 0; i < 3; i++){
//         console.log(i)
//     }
//     console.log('i out', i)
// }
// for(let i = 0; i < 3; i++){
//     for(let i = 0; i < 3; i++){
//         console.log(i)
//     }
//     console.log('i out', i)
// }

// --------------------------------
// var elements = [{}, {}, {}]
// for(var i = 0; i< elements.length; i++){
//     elements[i].onclick = (function (i) {
//         return function () {
//             console.log(i)
//         }
//     })(i)
// }
// for(let i = 0; i< elements.length; i++){
//     elements[i].onclick = function () {
//         console.log(i)
//     }
// }
// elements[0].onclick()
// --------------------------------------------
// for(let i = 0; i< 3;i++){
//     let i = 'foo'
//     console.log(i)
// }
// let i = 0
// if(i < 3){
//     let i = 'foo'
//     console.log(i)
// }
// i++
// if(i < 3){
//     let i = 'foo'
//     console.log(i)
// }
// i++
// if(i < 3){
//     let i = 'foo'
//     console.log(i)
// }
// i++
// if(i < 3){
//     let i = 'foo'
//     console.log(i)
// }
// i++
// ------------------------------------
// let 没有声明提升
// console.log(foo)
// var foo = 'foo'

// console.log(foo)
// let foo = 'foo'

const

  • let基础上多了只读特性, 声明过后不允许在被修改且变量声明必须直接赋值
  • 最佳实践: 不用var, 主用const, 配合let
// const变量声明 不能修改
// const name = 'const'
// name = 'liuchao'

// const变量声明必须直接赋值
// const name 
// name = 'const'

// ------------------
// const obj = {}
// obj.name = 'const'

// obj = {}

数组的解构

const arr = [100, 200, 300]

// const foo = arr[0]
// const bar = arr[1]
// const baz = arr[2]
// const [foo, bar, baz] = arr
// console.log(foo, bar, baz)

// const [, , baz] = arr
// console.log( baz)

// const [foo, ...rest] = arr
// console.log(rest)

// const [foo, bar, baz, more] = arr
// console.log(more)

// const [foo, bar, baz, more = 'more'] = arr
// console.log(more)

对象的解构

const obj = {name: 'const', age: 10}
// const {name, age} = obj
// console.log(name, age)

// const name = 'tom'
// const {name: objName = 'objName'} = obj 
// console.log(objName, name)

const {log} = console
log('xxx')
log('aaa')
log('adkdk')

模版字符串字面量

const str = 'hello es2015, this is a string'
const str = `hello es2015, 
this is a \`string\``
// ``内支持转义字符  支持换行 多行字符串 

console.log(str)

// 支持变量嵌入 简单运算 js内置函数
const name = 'liuchao'
const msg = `hey, ${name}--------${1 + 3}---------${Math.random()}`
console.log(msg)

模版字符串标签函数

// const str = console.log`hello world`

const name = 'luchao'
const gender = true 

function myTagFunc(str, name, gender){
    // console.log(str, name, gender)
    // return '123'
    const sex = gender ? 'man' : 'women'
    return str[0] + name + str[1] + sex + str[2]
}


const result = myTagFunc`hey, ${name} is a ${gender}.`
console.log(result)

字符串的扩展方法

  • includes
  • startWith
  • endWith
const  msg = 'Error: foo is not defined.'

console.log(
    msg.startsWith('Error'),
    msg.endsWith('.'),
    msg.includes('foo')
)

参数默认值

// function foo(enable){
//     // enable = enable || true 
//     enable = enable === undefined ? true : enable
//     console.log('foo invoked - enable: ')
//     console.log(enable)
// }
// 带默认值的参数在最后
function foo(bar,enable = true){
    console.log('foo invoked - enable: ')
    console.log(enable)
}

foo(false)

剩余参数

// function foo(){
//     console.log(arguments)
// }

// ...操作符只能用在最后一个参数 并且只能使用一次
function foo(...args){
    console.log(args)
}
foo(1, 2, 4, 45)

展开数组参数

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

// console.log(
//     arr[0],
//     arr[1],
//     arr[2]
// )

// console.log.apply(console, arr)


console.log(...arr)

箭头函数

  • 箭头函数不会改变this的指向
// function inc(num){
//     return num + 1 
// }
// const inc = n => n+1 

// console.log(inc(100))


const arr = [1, 2, 3, 4, 5, 6, 7]
// arr.filter(function(item){
//     return item % 2
// })

const result = arr.filter(item => item % 2)
console.log(result)


// 箭头函数与 this

const person = {
    name : 'tom',
    // sayHi: function(){
    //     console.log(`hi, my name is ${this.name}`)
    // }
    sayHi: () => {
        // 箭头函数没有this机制 不会改变this指向
        console.log(`hi, my name is ${this.name}`)
    },
    sayHiAsync: function () {
        // const _this = this
        // setTimeout(function(){
        //     console.log(_this.name)
        // }, 1000)
        setTimeout(()=>{ 
            console.log(this.name)
        }, 1000)
    }
}
person.sayHi()
person.sayHiAsync()

对象字面量增强

  • 计算属性名
const bar = '2233'
const obj = {
    name: '111',
    // bar: bar,
    bar,
    // method1: function(){
    //     console.log('mothed111')
    // },
    method1(){
        console.log('mothed111')
        console.log(this)
    },
    // Math.random(): 111

    // 计算属性名
    [Math.random()]: 1113
}
obj[Math.random()] = 1112 
console.log(obj)
obj.method1()

对象扩展方法

  • Object.assign 将多个源对象中的属性复制到一个目标对象中(如果有相同, 源对象中的属性就会覆盖目标对象中的属性)
// const source = {
//     a: 111, 
//     b: 233
// }
// const source2 = {
//     d: 111, 
//     f: 233
// }
// const target = {
//     a: 444,
//     c: 666
// }
// const result = Object.assign(target, source, source2)

// console.log(result)
// console.log(result === target)



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

const obj = {name: 'global obj'}

func(obj)
console.log(obj)
  • is
console.log(
    0 == false,
    0 === false,
    +0 === -0,
    NaN === NaN,
    Object.is(+0, -0),
    Object.is(NaN, NaN),
)

Proxy 代理对象(Object.defineProperty)以及Proxy的优势

  • defineProperty只能监视属性的读写 Proxy能够监视更多对象操作(delete操作、对对象方法的调用等)
  • Proxy更好的支持数组对象的监视 (以往监视数组操作方法是重写数组的操作方法)
  • Proxy是以非侵入的方式监管了对象的读写(一个定义好的对象,不需要对对象本身进行操作就可以监视到内部成员的读写, 而defineProperty通过特定的方式单独定义需要被监视的属性,需要去做很多额外的操作)
// Proxy 对象

const person = {
    name: 'liuchao',
    age: 18
}

// 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 = 99  

// personProxy.gender = 'man'

// console.log(personProxy.name)
// console.log(personProxy.xxx)

// -----------------------------------
//  Proxy 监听对象delete属性行为
// const personProxy = new Proxy(person, {
//     deleteProperty(target, property){
//         console.log('delete', target, property)
//         delete target[property]
//     }
// })

// delete personProxy.age 
// console.log(person)

// -------––-------––-------––-------––-------––
// 如何使用Proxy对象监听数组
const list = []
const listProxy = new Proxy(list, {
    set(target, property, value){
        console.log('set', property, value)
        target[property] = value 
        return true //表示设置成功
    }
})

listProxy.push(100)

Reflect 统一的对象操作API

  • 属于一个静态类, 不能通过new 构建实例对象, 只能调用静态类中的一些方法
  • Reflect内部封装了一系列对对象的底层操作(14个, 一个被废弃; 方法名和Proxy中的方法名相同)
  • Reflect成员方法就是Proxy处理对象的默认实现
  • 最大的作用 统一提供一套用于操作对象的API
// Reflect 对象

// const obj = {
//     foo: '122', 
//     bar: '222'
// }
// const proxy = new Proxy(obj, {
//     get(target, property){
//         console.log('watch login~')
//         return Reflect.get(target, property)
//     }
// })
// console.log(proxy.foo)


// example

const obj = {
    name: 'liuchao',
    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))

Promise

  • 一种更优的异步编程解决方案, 解决了传统异步编程中回调函数嵌套过深的问题

class类

  • 静态成员 static
  • 类的继承 extends
// Class 关键词

// function Person (name){
//     this.name = name
// }
// Person.prototype.say = function(){
//     console.log(`hi, my name is ${this.name}`)
// }

// class Person {
//     constructor(name){
//         this.name = name 
//     }
//     say(){
//         console.log(`hi, my name is ${this.name}`)
//     }
// }
// const p = new Person('liuchao')
// p.say()

// ----------------------------------------
// 静态方法 static
// class Person {
//     constructor(name){
//         this.name = name 
//     }
//     say(){
//         console.log(`hi, my name is ${this.name}`)
//     }
//     static create(name){
//         return new Person(name)
//     }
// }
// Person.create('liuchao').say()

// ----------------------------------------
// 类的继承 extends
class Person {
    constructor(name){
        this.name = name 
    }
    say(){
        console.log(`hi, my name is ${this.name}`)
    }
}

class Student extends Person {
    constructor(name, num){
        super(name)
        this.num = num
    }
    hello(){
        super.say()
        console.log(`my school number is ${this.name}`)
    }
}
const s = new Student('liuchao', 200)
s.hello()

Set数据结构

const s = new Set()
// 向Set数据结构中添加数据 重复添加会覆盖(后边覆盖前边的)
s.add(1).add(2).add(3).add(4).add(1)
console.log(s)

// 遍历成员
s.forEach(i => console.log('foreach' + i))

for(let i of s){
    console.log('for+ of' + i)
}

// 获取Set数据集合的长度
console.log(s.size)

// 判断Set数据中是否有某个元素
console.log(s.has(100))

// 删除Set数据中某个元素
console.log(s.delete(1), s)
// 清除Set数据中所有元素
console.log(s.clear(), s)


// 作用 : 数组去重
const arr = [1, 1, 3, 4, 2, 4, 2]
// const result = Array.from(new Set(arr))
const result = [...new Set(arr)]
console.log(result)

Map数据结构

  • 普通对象只能使用string作为键值(就算不是也会转换成string)
  • Map数据结构键值可以为任意值
// const obj = {}
// obj[true] = 'value'
// obj[123] = 'value'
// obj[{a:1}] = 'value'

// console.log(Object.keys(obj))
// console.log(obj['[object Object]'])


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)
})

Symbol 一种全新的原始数据类型

  • 最主要的作用就是为对象添加独一无二的属性名
  • 唯一性
// // shared.js ======================

// const cache = {}

// // a.js ===========================

// cache['foo'] = Math.random()
// cache['a_foo'] = Math.random()

// // b.js ===========================

// cache['foo'] = '123'
// cache['b_foo'] = '123'

// console.log(cache)

const s = Symbol()
console.log(s)
console.log(typeof s)

console.log(Symbol() === Symbol())

console.log(Symbol('foo'))
console.log(Symbol('bar'))
console.log(Symbol('baz'))


const obj = {
    [Symbol()]: '122'
}
console.log(obj)


// a.js ================================

const name = Symbol()
const person = {
    [name]: 'liuchao',
    say(){
        console.log(this[name])
    }
}

// b.js ================
// console.log(person[Symbol()]) //得不到结果
person.say()



// Symbol补充
// 唯一性
console.log(
    Symbol() === Symbol(),
    Symbol('foo') === Symbol('foo'),
)

// 全局服用一个相同的Symbol值 方式:1. 全局变量 2. Symbol.for方法
const s1 = Symbol.for('foo')
const s2 = Symbol.for('foo')
console.log(s1 === s2)
// ***** 特别注意: Symbol.for方法中维护的注册表是字符串string关联的, 非string也会转换成string
console.log(
    Symbol.for(true) === Symbol.for('true')
)

// Symbol提供的Symbol常量
console.log(Symbol.iterator)
console.log(Symbol.hasInstance)

const obj1 = {
    [Symbol.toStringTag]: 'Symbol'
}

console.log(obj1.toString())


// Symbol作为键值通过for in循环无法拿到 Object.key()也无法获取到 字符串化JSON.stringigy也会被忽略掉

const obj2 = {
    [Symbol()]: '222',
    name: 'liuchao'
}
for(let key in obj2){
    console.log(key)
}
console.log(Object.keys(obj2))
console.log(JSON.stringify(obj2))

// 可以通过Object.getOwnPropertySymbols()
console.log(Object.getOwnPropertySymbols(obj2))

BigInt 原始数据类型(用于储存更长的数字) 处在stage-4阶段

for of循环 作为遍历所有数据结构的统一方式

  • ES2015提供了Iterable接口(可迭代接口)
  • 实现Iterable接口就是for…of的前提
  • 实现可迭代接口
  • 迭代器模式
  • 迭代器意义: 对外提供统一遍历接口, 不用关心数据内部结构
const arr = [100, 200 , 399 ,3999]

// for(const item of arr){
//     console.log(item)
// }

// arr.forEach(item => {
//     console.log(item)
// })
// for of 可以使用break关键字 forEach循环不可以

// for(const item of arr){
//     console.log(item)
//     if(item > 200){
//         break
//     }
// }

// arr.forEach(item => {
//     console.log(item)
//     // if(item > 200){
//     //     break
//     // }
// })

// 终止遍历方法 arr.some() arr.every()


// ----------------------------------------------
// 遍历Set数据和Map数据
const s = new Set(['foo', 'bar'])
for(const item of s){
    console.log('set ' + item)
}
const m = new Map()
m.set('foo', '133')
m.set('bar', '13dkdk')
for(const [key, value] of m){
    console.log('map', key, value)
}

// -----------------------------
// 遍历普通对象
const obj = {
    foo: 122,
    bar: 333
}
// for(const item of obj){ //TypeError: obj is not iterable 不可被迭代
//     console.log('obj  ' + item) 
// }

迭代器[Iterator]

// 迭代器 [Iterator]

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())
console.log(iterator.next())

// 实现可迭代接口
// const obj = {
//     [Symbol.iterator]: function(){ //Iterator接口
//         return {
//             next: function(){ //IteratorREsult
//                 return {
//                     value: 'liuchao',
//                     done: true
//                 }
//             }
//         }
//     }
// }

const obj = {
    store: ['foo', 'bar', 'baz'],
    [Symbol.iterator]: function(){ //Iterator接口
        let index = 0
        const self = this
        return {
            next: function(){ //IteratorREsult
                const result = {
                    value: self.store[index],
                    done: index >= self.store.length
                }
                index++
                return result
            }
        }
    }
}

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


// 迭代器模式

// 场景: 多人协同开发一个任务清单应用

// 我的代码=====================

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

    each(callback){
        const all = [].concat(this.life, this.learn, this.work)
        for(const item of all){
            callback(item)
        }
    },

    [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
                }
            }
        }
    }
}

// 你的代码=====================
// for(const item of todos.life){
//     console.log(item)
// }
// for(const item of todos.learn){
//     console.log(item)
// }
// for(const item of todos.work){
//     console.log(item)
// }

todos.each(item => {
    console.log(item)
})
console.log('-----------------')
for(const item of todos){
    console.log(item)
}

生成器函数Generator

  • 避免异步编程中回调嵌套过深,从而提供更好的异步编程解决方案
// function * foo(){
//     console.log('foo')
//     return 100
// }
// const result = foo()
// console.log(result.next())

function * foo(){
    console.log(11111)
    yield 100
    console.log(2222)
    yield 200
    console.log(3333)
    yield 300
}
const generator = foo()
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())


// ---------------------------------
// 生成器的应用 Generator

// 案例一: 发号器

console.log('-----------------------------')
// 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)
// console.log(idMaker.next().value)

// 案例二: 使用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,'yield')
}

ES Modules 语言层面的模块化标准

ES2016

    1. Array.prototype.includes
    1. 指数运算符 console.log(2 ** 20)
// 1. Array.prototype.includes
const arr = ['foo', 1, NaN, false]

// indexOf不能用于查找NaN
console.log(arr.indexOf('foo'))
console.log(arr.indexOf('bar'))
console.log(arr.indexOf(NaN))
console.log(arr.includes('foo'))
console.log(arr.includes('bar'))
console.log(arr.includes(NaN))

// 指数运算符

console.log(Math.pow(2, 10))

console.log(2 ** 20)

ES2017

    1. Object.values
    1. Object.entries
    1. Object.getOwnPropertyDescriptors
    1. String.prototype.padStart / String.prototype.padEnd
    1. 在函数参数中添加尾逗号
    1. Async/await
const obj = {
    foo: 'value1',
    bar: 'value2'
}
// - 1. Object.values

console.log(Object.values(obj))

// - 2. Object.entries
console.log(Object.entries(obj))
for(const [key, value] of Object.entries(obj)){
    console.log(key, value)
}
console.log(new Map(Object.entries(obj)))
// - 3. Object.getOwnPropertyDescriptors

const p1 = {
    firstName: 'lei',
    lastName: 'wang',
    get fullName(){
        return this.firstName + ' ' + this.lastName
    }
}
console.log(p1.fullName)

// const p2 = Object.assign({}, p1)
// p2.firstName = 'liuchao'
// console.log(p2.fullName)


const descriptors = Object.getOwnPropertyDescriptors(p1)
console.log(descriptors)
const p2 = Object.defineProperties({}, descriptors)
p2.firstName = 'liuchao'
console.log(p2.fullName)


// - 4. String.prototype.padStart / String.prototype.padEnd

const books = {
    html: 3, 
    css: 15, 
    js: 22
}
// for(const [key, value] of Object.entries(books)){
//     console.log(key, value)
// }
for(const [key, value] of Object.entries(books)){
    console.log(`${key.padEnd(16, '-')}|${value.toString().padStart(3, '0')}`)
}


// - 5. 在函数参数中添加尾逗号

function foo2(bar, baz,) {
    return 100
}

const arr2 = [100,200,300,]
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页