前端路 - ES6

作用域


ES6 在全局作用域、局部作用域外,新增了一个块级作用域。在 { } 中使用 let / const 则会形成块级作用域,在 “块” 外层不能获取到 “块” 中的变量。在 for 循环中,for 的条件语句中声明的参数与其执行语句中声明的参数之间互相不影响,互相独立。可视为 for 循环中嵌套了两层作用域。

for (let i = 0; i < 3; i++) {
    let i = 'Azer';
    console.log(i);
}
// Azer Azer Azer

 

解构赋值


数组的解构

const arr = [100, 200, 300]

// 命名并获取对应位置的元素
const [foo, bar, baz] = arr;

// 获取某个特定位置的元素,空缺该元素前方的参数位
const [, , baz] = arr;

// 获取包含某个特定位置之后的所有元素的数组
const [foo, ...rest] = arr
// rest => [200, 300]

// 当解构长度大于原数组长度是,超出部分则会返回 undefined
// 可以通过设置默认值,让超出部分返回默认值
const [foo, bar, baz = 123, more = 'default value'] = arr

对象的解构

const obj = {name: 'Azer', age: 25}
// 解构
const {name, age} = obj
// 重命名
const {name: na} = obj
// 默认值
const {age = 20} = obj

 

模板字符串


语法

`This is a ${string}`

带标签的模板字符串

  • 在模板字符串前添加标签(一个特殊的函数)
  • 此时,模板字符传向函数中传入的第一个参数是一个数组,数组中包含的是字符串中按表达式 ${} 分割后的各个部分的字符串
  • 标签函数还可以通过键名获取到字符串中对应的参数、表达式的值
  • 标签函数的使用,可以对模板字符串进行自定义设置,如对字符串进行校验、替换等。
function log(strings) {
    console.log(strings)
}
const name = 'Azer'
const result = log`Hi, my name is ${name}.`
// result => [ 'Hi, my name is ', '.' ]

 

字符串扩展方法


includes()

  • 字符串中是否包含指定的字符或字符串
  • 接收两个参数
    • 第一个参数,在此字符串内搜索的目标字符串

    • 第二个参数为可选参数,表示在字符串中开始搜索的位置(默认为0)

starsWith()

  • 字符串中是否以指定内容开头
  • 接收两个参数
    • 第一个参数,在此字符串内搜索的目标字符串

    • 第二个参数为可选参数,表示在字符串中开始搜索的位置(默认为0)

endsWith()

字符串中是否以指定内容结尾

 

rest 操作符


语法

...rest

接收剩余参数

function(arg1, ...rest)
  • 通过 ...rest 来获取指定位置往后的所有参数
  • rest 为一个数组
  • ...rest 必须在参数末尾,其后不能再有其他参数
  • ...rest 仅能使用一次
  • rest 参数可以替换 'arguments' 类数组的使用

展开数组

const arr = ['foo', 'bar', 'baz']
// 手动 ==> 无法应对不定项
console.log(arr[0], arr[1], arr[2])
// ==>
console.log.apply(console, arr)
// ==>
console.log(...arr)

拷贝对象

  • 用于拷贝对象时,拷贝后的对象与源对象不是同一个对象,即执行的是“深”拷贝
  • 拷贝的对象,其属性值如果也是一个对象,则此时,两个对象的对应的属性值是同一个对象
  • rest 操作符用于拷贝对象时,对于第一层,执行的是值引用,如果存在属性值为对象时,不用对子层级进行“深拷贝”
const cls = {
    student1: {
        name: 'Azer',
        age: 25
    }
}

let obj1 = { ...obj }

console.log(obj === obj1) // false
console.log(obj.student1=== obj1.student1) // true

 

箭头函数


语法

() => {}
const add = (m, n) => m + n;
const add1 = (m, n) => { return m + n };

注意事项

若使用 { } ,则需要通过 return 来返回值

关于 this

箭头函数中是不存在 this 机制的。因此,箭头函数不会改变 this 的指向。

const person = {
    name: 'Azer',
    sayHi: name => {
        console.log(`Hi, my name is ${ this.name }`)
    }
}
// Hi, my name is undefined
// 此时,this 依旧指向全局,而不是 person 实例

 

对象


字面量的增强

  • 当设置的变量名跟对象的属性值一致时,可以直接写变量名
  • 计算属性名,可以通过 [ ] ,使用表达式作为对象的属性名
const bar = '233'
const obj = {
    foo: 423,
    bar,
    [Math.random()]: 'a xi ba'
}

Object.assign()

  • 将多个源对象中的属性复制到一个目标对象中
  • 若源对象和目标对象中存在同名属性,源对象中的值会覆盖目标对象中对应的值
  • 当存在多个源对象时,源对象会逐个覆盖到目标对象中
const src1 = { a: 'src1', b: 'src1' }
const src2 = { a: 'src2', d: 'src2' }
const target = { a: 'target', c: 'target'}

const result = Object.assign(target, src1, src2)
console.log(target) // { a: 'src2', c: 'target', b: 'src1', d: 'src2' }
console.log(result === target) // true

Object.is()

  • 用于判断两个值是否为同一个值
  • 满足的条件
    • 都是 undefined
    • 都是 null
    • 都是 true 或 false
    • 都是相同长度的字符串且相同字符按相同顺序排列
    • 都是相同对象(意味着每个对象有同一个引用)
    • 都是数字且
      • 都是 +0
      • 都是 -0
      • 都是 NaN
      • 都是非零而且非 NaN 且为同一个值
console.log(NaN === NaN)
// false
console.log(Object.is(NaN, NaN))
// true

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

 

Proxy


对比 Object.defineProperty()

  • defineProperty 只能监视对象属性的读写
  • Proxy 能够监听更多的对象操作(如删除)
  • Proxy 更好的支持数组对象的监视
  • Proxy 是以非侵入的方式监管了对象的读写
    • 即,Proxy 不需要通过直接操作创建的对象去监听对象

对象的代理

const person = {
    name: 'cyz',
    age: 25
}

const personProxy = new Proxy(person, {
    get(target, property) {
        return property in target ? target[property] : 'default'
    },
    set(target, property, value) {
        if (property === 'age' &&
            !Number.isInteger(+value)) {
            throw new TypeError(`${ value } is not an int`)
        }
        target[property] = value
    },
    deleteProperty (target, property) {
        delete target[prpperty]
    }
})
console.log(personProxy.name) // cyz
console.log(personProxy.a) // default
personProxy.age = '23'
console.log(personProxy.age) // 23
delete personProxy.age
console.log(person)

handler

方法

触发方式

get

读取某个属性

set

写入某个属性

has

in 操作符

deleteProperty

delete 操作符

getPrototypeOf

Object.getPrototypeOf()

setPrototypeOf

Object.setPrototypeOf()

isExtensible

Object.isExtensible()

preventExtensions

Object.preventExtensions()

getOwnPropertyDescriptor

Object.getOwnPropertyDescriptor()

defineProperty

Object.defineProperty()

ownKeys

Object.getOwnPropertyNames()

Object.getOwnPropertySymbols()

apply

调用一个函数

construct

用 new 调用一个函数

 

对数组对象的监听

const list = []
const listProxy = new Proxy(list, {
    set (target, property, value) {
        console.log('set', property, value)
        target[property] = value
        return true // 表示设置成功
    }
})
listProxy.push(100)
// set 0 100
// Proxy 会自动查询数组内元素的下标作为 property

 

Reflect 对象


Reflect 对象统一提供一套用于操作对象的API(静态函数)

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

API

方法

描述

对应

apply()

对一个函数进行调用操作,同时传入一个数组作为调用参数

function.prototype.apply()

construct()

对构造函数进行 new 操作

new target(...args)

defineProperty()

 

Object.defineProperty()

deleteProperty()

作为函数的 delete 操作符

delete target[key]

get()

获取对象身上的某个属性的值

target[name]

getOwnPropertyDescriptor()

 

Object.getOwnPropertyDescriptor()

getPrototypeOf()

 

Object.getPrototypeOf()

has()

判断一个对象是否存在某个属性

in 运算符

isExtensible()

 

Object.isExtensible()

ownKeys()

返回一个包含所有自身属性(不包含继承属性)的数组

Object.keys()

preventExtensions()

 

Object.preventExtensions()

set()

将值分配给属性的函数

 

setPrototypeOf()

 

Object.setPrototypeOf()

 

类(class)


案例

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

let person = new Person()

方法

  • 实例方法:通过这个构造函数所构造的对象去调用
  • 静态方法:直接通过类型本身去调用,通过 static 关键字声明
// 承上
const tom = Person.create('tom')
tom.say()

类的继承

class Student extends Person {
    constructor(name, number) {
        super(name) // 始终指向父类,即调用父类中对应的方法(函数)
        this.number = number
    }
    
    hello() {
        super.say()
        console.log(`My number is ${this.number}`)
    }
}
const s = new Student('Azer', '55')
s.hello()

 

Set


Set 是一个数据集合,是 ES6 中新定义的数据结构,类似于数组,但是 Set 结构对象中不允许存在重复项。添加的项若存在重复,则会被忽略掉。

Set 原型方法

方法(Set.prototype)

描述

add(value)

在对象尾部添加一个元素,返回该对象

clear()

移除对象内所有对象

delete(value)

如果元素存在,则移除该元素

entries()

返回一个新的迭代器对象,该对象包含原对象中的按插入顺序排列的所有元素的值的 [value, value] 数组。即,与 Map 对象类似,以每个元素的值作为键名,生成键值对数组

forEach(callback())

按照插入顺序,为每一个值调用一次 callback

has(value)

判断对象中是否存在某一个值

values()

返回一个新的迭代器对象,该对象包含对象中的按插入顺序排列的所有元素的值

keys()

与 values() 相同

常用用途

// 去重
const arr = [4,3,7,6,4,3,7,2,9]
const result = Array.from(new Set(arr))
// ===> const rusult = [...new Set(arr)]
console.log(result) // [4,3,7,6,2,9]

 

Map


Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值

与 Object 的区别

  • 一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
  • Map 中的键值是有序的(FIFO 原则,即先进先出),而添加到对象中的键则不是。
  • Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
  • Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

案例

// key 是字符串
var myMap = new Map();
var keyString = "a string"; 
myMap.set(keyString, "和键'a string'关联的值");
myMap.get(keyString);    // "和键'a string'关联的值"
myMap.get("a string");   // "和键'a string'关联的值"
                         // 因为 keyString === 'a string'

// key 是对象
var myMap = new Map();
var keyObj = {}, 
myMap.set(keyObj, "和键 keyObj 关联的值");
myMap.get(keyObj); // "和键 keyObj 关联的值"
myMap.get({}); // undefined, 因为 keyObj !== {}

// key 是函数
var myMap = new Map();
var keyFunc = function () {}, // 函数
myMap.set(keyFunc, "和键 keyFunc 关联的值");
myMap.get(keyFunc); // "和键 keyFunc 关联的值"
myMap.get(function() {}) // undefined, 因为 keyFunc !== function () {}

// key 是 NaN
var myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN); // "not a number"
var otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number"

 

Symbol


  • Symbol 存在唯一性
Symbol() === Symbol() // false
Symbol('foo') === Symbol('foo') // false
  • Symbol 的对应性是依据传入的字符串
const s1 = Symbol.for('boo')
const s2 = Symbol.for('boo')
console.log(s1 === s2) // true
  • Symbol.for() 参数的值为字符串,若传入的值不是字符串,则会默认被转化为字符串
console.log(Symbol.for(true) === console.log('true')) // true
  • 使用 Symbol 作为属性名,该属性无法被 for..in..,Object.keys(),JSON.stringify() 获取到
const obj = {
    [Symbol()]: 'symbol value',
    foo: 'normal value'
}
for (var key in obj) {
    console.log(key)
} // foo
console.log(Object.keys) // ['foo']
console.log(JSON.stringify(obj)) // {"foo":"normal value"}
// 获取方法
console.log(Object.getOwnPropertySymbols(obj)) // [ Symbol() ]
  • 目前,Symbol 最主要的作用,是为对象添加一个独一无二的属性名

 

for...of...


概述

  • 将作为遍历所有数组结构的统一方式
  • 可以通过 break 直接终止循环
  • 无法遍历 Object 对象

迭代器(Iterator)

  • 可以被 for...of... 遍历的对象,内部必须有一个返回迭代器的 iterator 方法
  • 迭代器内部必须有一个 next 方法,作为返回一个迭代结果对象的接口
  • 迭代结果对象中,需要有一个 value 作为当前迭代到的数据,以及一个值为布尔值的属性 done 来表示当前迭代是否结束
  • 当迭代结束时,返回的迭代结果对象为:
{ value: undefined, done: true }

案例

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

for (const item of obj) {
    console.log('循环体', item)
}
// 循环体 foo 循环体 bar 循环体 baz

 

生成器(Generator)


概念

  • 通过在声明函数时添加 * 作为标识
  • 可以使用 yield 替代 return 的使用
  • 通过调用函数的 next 方法来触发 yield(也由此可见,Generator 支持 Iterator 接口)
  • 当函数体中存在多个 yield 时,可以通过调用 next 方法,按顺序触发函数的执行

案例

function* foo() {
    console.log('111')
    yield 100
    console.log('222')
    yield 200
    console.log('333')
    yield 300
}
const generator = foo()
console.log(generator.next()) // 111 { value: 100, done: false}
console.log(generator.next()) // 200 { value: 200, done: false}
console.log(generator.next()) // 300 { value: 300, done: false}
console.log(generator.next()) // { value: undefined, done: true}

应用

// 案例一:发号器
function* createIdMaker() {
    let id = 1
    while (true) {
        yield id++
    }
}
const idMaker = createIdMaker()
console.log(idMaker.next()) // { value: 1, done: false }
console.log(idMaker.next()) // { value: 2, done: false }
console.log(idMaker.next()) // { value: 3, done: false }

// 案例二:使用 Generator 函数实现 iterator 方法
const todos = {
    life: ['吃饭', '睡觉', '打豆豆'],
    learn: ['语', '数', '英'],
    work: ['A', 'B'],
    [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)
}
// 吃饭 睡觉 打豆豆 语 数 英 A B 

以上,为 ES 2015 内容


 

ES 2016 新增特性


  • 判断少数组中是否存在某一个元素
// Array.prototype.includes
let arr = ['a','v','b','d']
arr.includes('a') // true
arr.includes('c') // false
  • 指数运算符
console.log(Math.pow(2, 10)) // 1024
// ===>
console.log(2 ** 10) // 1024

 

ES2017 新增特性


  • Object.values
    • 返回对象中所有的值所组成的数组
  • Object.entries
    • 以数组的形式返回对象中的键值对
    • 使得对象可以通过 for...of... 来遍历
    • 可以借助这个方法,将 Object 对象转化为 Map 对象
const obj = {
    value1: 'foo',
    value2: 'bar'
}

console.log(Object.values(obj)) // ['foo', 'bar']

console.log(Object.entries(obj)) // [['value1', 'foo'], ['value2', 'bar']]
for (const [key, value] of Object.entries(obj)) {
    console.log(key, value)
} // value1 foo // value2 bar
console.log(new Map(Object.entries(obj))) // Map { 'value1' => 'foo', 'value2' => 'bar' }
  • Object.getOwnPropertyDescriptors
  • String.prototype.padStart / String.prototype.padEnd
    • 用给定的字符串去填充目标字符串知道长度达到指定长度
const books = { html: 4, css: 3, javascript: 10 }
for (const [name, count] of Object.entries(books)) {
    console.log(`${name.padEnd(18, '=')}|${count.toString().padStart(3, '0')}`)
}
// html==============|004
// css===============|003
// javascript========|010

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值