美文网首页
ES2015(ES6)学习手册

ES2015(ES6)学习手册

作者: 贰玖是只猫 | 来源:发表于2021-03-22 22:55 被阅读0次

作用域

  • 全局作用域
  • 函数作用域
  • 块级作用域(es6)

let

  • let 声明的变量只在所处的块级有效
  • let没有变量声明提升

需要注意的一点:

for (let i = 0;i < 3; i++) {
     let i = "xxx"
     console.log(i);
}

其实在此处是两层的块级作用域

const

  • const 与 let一样作用域都是块级
  • const只用来声明常量
  • const声明的时候必须复制,否则会报错
const obj = {}
obj.name = "sam"

这种情况不会报错,根本原因是obj指向的地址是没变的

数组的解构

const [first, second, third] = [1,2,3]
const [first, second, third, fourth = 4] = [1,2,3]
const [first, ...rest] = [1,2,3,4]

对象的解构

const obj = {name: "xxx", age: 18}
const {name,age} = obj

模板字符串

const param = "world"
const str = `hello,  //可换行
${param}`   //嵌入变量以及script语句
console.log(str)

还一个比较特殊的使用方式是带标签

const  name = "sam"

function tagFn (string, name) {
    console.log(string, name) // 可以在这部分做对字符串的修饰
    return string[0] + name + string[1]
}

const result = tagFn`hi, ${name}.`
console.log(result)

字符串扩展方法

includes()
startsWith()
endsWith()

参数默认值

function foo (a = 1) {
    console.log(a )
}
foo()

剩余参数

function foo (...rest) { //只能用在形参的最后一位 并且只能使用一次
    console.log(rest)
}
foo(1,2,3,4)

展开数组

const arr = [1,2,3]
console.log.apply(console, arr)//两种方式等同
console.log(...arr)

箭头函数

const inc = (n,m) => {
    return n + m
}
console.log(inc(1,2))

箭头函数不会改变this的指向

对象字面量的增强

const bar = "2"
const obj = {
    foo: 1,
    bar,
    fn() {
        console.log("fnfnfnfnfnfn")
    }
}
obj[1+1] = 3
obj.fn()

对象的扩展方法

Object.assign()

const obj1 = {
    a:1,
    b:2
}
const obj2 = {
    a:3,
    c:4
}
const obj = Object.assign(obj1, obj2)
console.log(obj)
console.log(obj === obj1)
//{ a: 3, b: 2, c: 4 }
//true

Object.is()

Object.is(+0 === -0)

Proxy

Proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作必须通过这层拦截

const person = {
    name: "sam",
    age: 18
}
const personProxy = new Proxy(person, {
    get(target, property) {
        
        return property in target ? target[property] : "default"
    },
    set(target, property, value) {
        if (property === "age") {
            if (!Number.isInteger(value)){
                throw new TypeError(`${value} is not an int`)
            }
        }
        target[property] = value
    }
})

personProxy.age = 12
personProxy.sex = "man"

我们发现proxyObject.defineProperty()的作用相似,那么两者有什么区别呢?

  • Object.defineProperty()只能监控到对象属性的读写
  • proxy 可监控更多操作例如属性删除,对象方法调用
handle 触发条件
get 读取某个属性
set 写入某个属性
has in 操作符
deleteProperty delete 操作符
getProperty Object.getPropertypeOf()
setProperty Object.setPrototypeOf()
isExtensible Object.isExtensible()
preventExtensions Object.preventExtensions()
getOwnPropertyDescriptor Object.getOwnPropertyDescriptor()
defineProperty Object.defineProperty()
ownKeys Object.keys() 、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()
apply 调用一个函数
construct 用 new 调用一个函数

对数组监视
本质: 重写数组的操作方法。
proxy监视数组

const list = []

const listProxy = new Proxy(list, {
    set(target, property, value) {
        console.log("push", property, value)
        target[property] = value
        return true
    }
})
listProxy.push(100)

非侵入便可监视

Reflect

Reflect 是一个静态类,使用方式类似Math
Reflect成员方法就是Proxy处理对象的默认实现。
Reflect提供了一套用于操作对象的API,详情见以上表格

const obj = {
    name: "zicoo",
    age: 18
}
// console.log("name" in obj)
console.log(Reflect.has(obj, "name"))
// console.log(delete obj[age])
console.log(Reflect.deleteProperty(obj, "age"))
// console.log(Object.keys(obj))
console.log(Reflect.ownKeys(obj))

Promise

提供了一种更优的异步编程方案
具体可见之前的文章《Promise核心功能从原理到实现

class 类

class Person {
    constructor (name) {
        this.name = name
    }
    say() {
        console.log(`my name is ${this.name}`)
    }
    static create(name) {
        return new Person(name)
    }
}

const zicoo = new Person("zicoo")
zicoo.say()
const sam = Person.create("sam")
sam.say()

class Student extends Person {
    constructor(name, number) {
        super(name)
        this.number = number
    }
    hello() {
        super.say()
        console.log("student say hello")
    }
}
const tom = new Student("tom", 10)
tom.hello()

Set 数据结构

  • 可看做集合
  • Set中数据不重复
const s = new Set();
s.add(1).add(2).add(1)
console.log(s)

//s.forEach()
//for (let i of s)
// s.zie
// s.has(1)
// s.delete(2)
// s.clear()

Set有个常见的场景是用来数组去重

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

Map数据结构

Object类似都是存的键值对,但是Object的key只能为String类型

const obj = {}
obj[true] = 123
obj[123] = 123
obj[{a: 1}] = 123
console.log(Reflect.ownKeys(obj))
//[ '123', 'true', '[object Object]' ]
console.log(obj[{}])
// 123

我们发现真正对象的key是字符串, 并且我们发现这么使用存在的其他问题。
那么Map的出现解决了这些问题

const m = new Map()
const tom = {name: "tom"}
m.set(tom, 90)
// m.get()
// m.delete()
// m.clear()
// m.forEach()

Symbol 数据类型

独一无二的值
最主要的作用是给对象增加一个独一无二的属性

// const obj = {
//     [Symbol("name")]: 123
// }
// console.log(obj)
// 场景  私有成员

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

以上就是最简单的使用,那么Symbol的其实使用场景呢

console.log(Symbol("foo") === Symbol("foo"))
console.log(Symbol.for("foo") === Symbol.for("foo"))
//false
//true
console.log(Symbol.for(true) === Symbol.for("true"))
// false       证明会将true 转成字符串

//Symbol 本身有好多方法的标识符
// eg: 
//Symbol.hasInstance
//Symbol.iterator

const obj = {}
console.log(obj.toString())
//[object Object]
const objX = {
    [Symbol.toStringTag] : "XObject"
}
console.log(objX.toString())
//[object XObject]

// 通过 for 无法不按理 objx中的 [Symbol.toStringTag], Object.keys 也不可以

console.log(Object.getOwnPropertySymbols(objX))
// [ Symbol(Symbol.toStringTag) ]

for ... of 循环

可遍历所有数据类型

基本用法

// 遍历数组
const arr = [100,200,300,400]
for (const item of arr) { 
    if (item > 100) {
        break
    }
    console.log(item)
}
// 遍历map
const m = new Map()
m.set("foo", 123)
m.set("bar", 234)
for(const [key,value] of m) {
    console.log(key, value)
}

当我们遍历数组时会出现什么情况

const obj = {name: "sam"}
for (const item of obj) {
    console.log(item)
}
//obj is not iterable

问题来了报错了! 其实 数据结构的 Iterable接口是使用 for ... of 的前提

迭代器

image.png
我们发现无论Array``Set``Map_proto_原型上都有Symbol(Symbol.iterator)这个方法。
image.png

我们发现这个iterator的作用相当于一个指针,每调用一次next(),都会将value指向下一个值,并且done来区分是不是遍历完成

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

//{ value: 'foo', done: false }
//{ value: 'bar', done: false }
//{ value: 'baz', done: false }
//{ value: undefined, done: true }

那我们简单实现一下可迭代接口Iterable

// 实现可迭代接口(Iterable)

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

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

生成器

function * foo() {
    console.log("111")
    yield 100
    console.log("222")
    yield 200
    console.log("333")
    yield 300
}

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



// 使用generator 改造 iterator 方法

const obj = {
    store: ["foo", "bar", "baz"],
    [Symbol.iterator]: function * () { // Iterable
        for(const item of obj.store) {
            yield item
        }
    }
}

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

它还有一个很重要的使用场景就是 异步编程, 可见之前的文章《异步编程(Promise、Generator、Async与Await)

ES Modules

后续有详细介绍。略

ES2016

  • Array.propotype.includes
  • 指数运算 eg: Math.pow(2, 10) === 2 ** 10

ES2017

  • Object.vaules: 返回所有值的数组
  • Object.entries: 返回所有键值对数组
  • Object.getOwnPropertyDescriptors: 获取所有属性 eg: get() set()
  • String.prototype.padStart/String.prototype.padEnd: 填充字符串前面或后面
  • Async/Await

相关文章

网友评论

      本文标题:ES2015(ES6)学习手册

      本文链接:https://www.haomeiwen.com/subject/pqyocltx.html