ECMAscript2015新特性

概述

  • ECMAScript是一门脚本语言,缩写为ES
  • 通常看作为JavaScript的标准化规范
  • 实际上JavaScript是ECMAScript的扩展语言
  • ECMAScript只提供了最基本的语法
  • JavaScript语言本身指的就是ECMAScript
  • 2015年开始,ES保持每年一个版本的迭代
  • 很多人也把ES2015称之为ES6
  • 也有很多人将ES6泛指ES2015之后的所有新版本

(浏览器中的JavaScript)
在这里插入图片描述

(node环境中的JavaScript)
在这里插入图片描述

(ES各个版本)
在这里插入图片描述

变化

  • 解决原有语法上的一些问题或者不足。例如let、const上的块级作用域等
  • 对原有语法进行增强。例如…展开、参数默认值、模板字符串等
  • 全新的对象、全新的方法、全新的功能。例如Promise等
  • 全新的数据类型和数据结构。例如Symbol、Set、Map等

let

作用域

  • 全局作用域
  • 函数作用域
  • 块级作用域

var 和 let 区别

作用域

  • var:全局作用域和函数作用域
  • let:块级作用域

(第一种)

if (true) {
    var value = "123"
}
console.log(value) // 123
if (true) {
    let value = "123"
}
console.log(value) // ReferenceError: value is not defined

(第二种)

for (var i = 0; i < 3; i++) {
	for (var i = 0; i < 3; i++) {
		console.log(i)
	}
	console.log("外循环:", i)
}

// 打印结果
// 0
// 1
// 2
// 外循环: 3
for (let i = 0; i < 3; i++) {
    for (let i = 0; i < 3; i++) {
        console.log(i)
    }
    console.log("外循环:", i)
}

// 打印结果
// 0
// 1
// 2
// 外循环: 0
// 0
// 1
// 2
// 外循环: 1
// 0
// 1
// 2
// 外循环: 2

(第三种)

var elements = [{}, {}, {}]
for (var i = 0; i < elements.length; i++) {
    elements[i].fun = function () { // 此处的 function 只是声明,并没有运行。在调用时才运行
        console.log(i)
    }
}
// i 是全局变量,此时的 i = 3

elements[0].fun()
elements[1].fun()
elements[2].fun()

// 打印结果
// 3
// 3
// 3

(可以通过闭包来解决上述问题)

var elements = [{}, {}, {}]
for (var i = 0; i < elements.length; i++) {
    elements[i].fun = function (i) {
        return function () { // 闭包缓存了 i 的值,在调用时会使用到
            console.log(i)
        }
    }(i) // 此处要调用
}
elements[0].fun()
elements[1].fun()
elements[2].fun()

// 打印结果
// 0
// 1
// 2
var elements = [{}, {}, {}]
for (let i = 0; i < elements.length; i++) {
    elements[i].fun = function () {
        console.log(i)
    }
}
elements[0].fun()
elements[1].fun()
elements[2].fun()

// 打印结果
// 0
// 1
// 2

let 在 for 循环中的特别之处

  • 此处的 i 有两个作用域:一个是 for 循环条件内部;一个是 for 循环体内部
for (let i = 0; i < 3; i++) {
    let i = "asd"
    console.log(i)

// 打印结果
// asd
// asd
// asd

变量提升问题

  • var 将变量的声明自动提到最前方
  • let 则不可以
// var 的变量已经声明,但是在此处没有赋值
console.log(value)
var value = "asd"

// 打印结果
// undefined
// 直接报错
console.log(value)
let value = "asd"

// 打印结果
// ReferenceError: Cannot access 'value' before initialization

const

  • 在let基础上多了“只读”属性,是指变量在声明过后不允许再被修改
const name = "asd"
name = "qqq"

// 打印结果
// TypeError: Assignment to constant variable.
  • 不允许修改是指,不能修改变量的内存指向,而不是不允许修改值
const obj = {}
obj.name = "qwe"
console.log(obj)

// 打印结果
// { name: 'qwe' }
  • 变量声明的同时,必须要赋值
const name
name = "asd"

// 打印结果
// SyntaxError: Missing initializer in const declaration

解构

数组的解构

  • 将变量放入对应的位置,可以拿到对应的值
const arr = [20, 50, 10]
const [num1, num2, num3] = arr
console.log(num1, num2, num3)

// 打印结果
// 20 50 10
  • 只是获取其中某些值,需要保留数据的基本结构。只能放在最后位置
const arr = [20, 50, 10]
const [, num2,] = arr
console.log(num2)

// 打印结果
// 50
  • 可以添加 … 表示从当前位置开始提取剩下的值
const arr = [20, 50, 10]
const [num1, ...rest] = arr
console.log(rest)

// 打印结果
// [ 50 , 10 ]
  • 解构的参数 > 数组个数时,返回 undefined
const arr = [20, 50, 10]
const [num1, num2, num3, more] = arr
console.log(more)

// 打印结果
// undefined
  • 在解构中,可以设置默认值
const arr = [20, 50, 10]
const [num1, num2, num3, more="new value"] = arr
console.log(more)

// 打印结果
// new value

对象的解构

  • 以对象的key作为解构途径
const obj = { name: "asd", age: 12 }
const { name } = obj
console.log(name)

// 打印结果
// asd
  • 对 对象解构中的变量 进行重命名
const obj = { name: "asd", age: 12 }
const name = "qwe"
const { name: objName } = obj
console.log(name)
console.log(objName)

// 打印结果
// qwe
// asd
  • 进行重命名之后的,使用原来的变量会报错
const obj = { name: "asd", age: 12 }
const { name: objName } = obj
console.log(name)

// 打印结果
// ReferenceError: name is not defined
  • 添加默认值
const obj = { name: "asd", age: 12 }
const { gender: objGender = "Female" } = obj
console.log(objGender)

// 打印结果
// Female

模板字符串

  • 使用反引号来创建字符串
  • 反引号中,使用反斜杠来转义反引号
const str = `hello es2015, this is a \`string\``
console.log(str)

// 打印结果
// hello es2015, this is a `string`
  • 支持换行
const str = `hello es2015, 

this is a \`string\``
console.log(str)

// 打印结果
// hello es2015, 
// 
// this is a `string`
  • 支持插值表达式 ${}
  • 插值表达式内,可以进行数学运算、接受方法返回值等
const name = "Eilsen"
const str = `my name is ${name}, my age is ${3 + 5}, -----${Math.random()}`
console.log(str)


// 打印结果
// my name is Eilsen, my age is 8, -----0.4345345433454454
  • 使用方法名,给模板字符串打上标签
const name = 'tom'
const gender = false

function myTagFunc (strings, name, gender) {
    console.log("function inner: ", strings, name, gender)
    const sex = gender ? 'man' : 'woman'
    return strings[0] + name + string[1] + sex + strings[2]
}

const result = myTagFunc`hello, ${name} is a ${gender}.`
console.log("outside result: ", result)

// 打印结果
// function inner: [ 'hello,' , ' is a ' , '.' ] tom false
// outside result: hello, tom is a woman.

字符串扩展方法

startsWith()

const message = 'today is a good day!'
console.log( message.startsWith( "today" ))

// 打印结果
// true

endsWith()

const message = 'today is a good day!'
console.log( message.endsWith( "day!" ))

// 打印结果
// true

includes()

const message = 'today is a good day!'
console.log( message.includes( "good" ))

// 打印结果
// true

参数默认值

  • 在参数列表内,使用=设置默认值
  • 有多个参数时,带有默认值的参数必须放在最后
function example ( param1, param2 = true ){
    console.log( param1 , param2 )
}
example("abc")

// 打印结果
// abc true

剩余参数

  • 使用 …args 方式来设置
  • …args 只能使用一次,且 args 是数组
  • 当有多个参数时,…args 只能放在最后
  • 可以代替 arguments 对象来获取参数
function example ( param1, ...args ){
    console.log( param1 , args )
}
example("abc" , 1 , 4 , 3 , 6 , false )

// 打印结果
// abc [ 1 , 4 , 3 , 6 , false ]

展开数组

const arr = [ 'apple' , 'banana' , 'grape' ]

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

// 原始方式2
console.log.apply( console , arr )

// 展开数组
console.log( ...arr )

// 打印结果
// 'apple'  'banana'  'grape'
// 'apple'  'banana'  'grape'
// 'apple'  'banana'  'grape'

箭头函数

原始函数转换为箭头函数

  • 使代码更简短、易读
// 原始函数
function example (value) {
    return value * value
}
console.log("example : ", example(5) )

// 箭头函数
const example2 = value => value * value
console.log("example2 : ", example2(5) )

// 打印结果
// 25
// 25

箭头函数不会改变this指向

  • 在普通函数里,this指向的是当前对象
  • 在箭头函数里,this指向的是箭头函数外部的this指向
/** 普通函数 */
const person = {
    name: "Linda",
    say: function () {
        console.log(`hello, I am ${this.name}`)
    },
    sayAsync: function () {
    
        // 使用闭包来缓存this的指向
        // const _this = this
        
        setTimeout(function () {
        
            //此时的function是放在全局环境下,所以this指向的是全局环境
            console.log(`async: hi, my name is ${this.name}`)
            
            // 使用闭包来缓存this的指向
            // console.log(`async: hi, my name is ${_this.name}`)
        }, 1000)
    }
}
person.say()
person.sayAsync()

// 打印结果
// hello, I am Linda
// async: hi, my name is undefined
/** 箭头函数 */
const person = {
    name: "Linda",
    say: () => {
    
        // 此时的 this 指向的是调用person的对象
        // 在 node环境 中,this = {}
        // 在 window环境中, this = window对象
        console.log(`hello, I am ${this.name}`)
    },
    sayAsync: function () {
    
        setTimeout(() => {
        
            // 箭头函数则是永远指向不变
            console.log(`async: hi, my name is ${this.name}`)
        }, 1000)
    }
}
person.say()
person.sayAsync()

// 打印结果
// hello, I am undefined
// async: hi, my name is Linda

对象字面量的增强

const name = "Linda"

const obj = {
    id:123,
    // 属性名和变量名一致,可以直接写变量名
    name, // name == name : name
    
    // 普通方法可以缩写
    // method: function(){
    //    console.log("method function")
    // }
    method(){
        console.log("method function")
    },
    
    // 计算属性名
    [ 1 + 2 ]: 123,
    [ Math.random() ]: 222,
}

对象常用方法

Object.assign()

  • 将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);

console.log(target);
console.log(returnedTarget);
console.log(target === returnedTarget)

// 打印结果
// { a: 1, b: 4, c: 5 }
// { a: 1, b: 4, c: 5 }
// true

Object.is()

  • 判断两个值是否为同一个值
console.log(
    0 == false,            // true
    0 === false,          // false
    Object.is(0, false)    // false
)

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

console.log(
    NaN == NaN,            // false
    NaN === NaN,          // false
    Object.is(NaN, NaN)    // true
)

Proxy()

  • 代理:用于定义基本操作的自定义行为
// 目标对象
const person = {
    name: "Linda",
    age: 22,
}

const proxy = new Proxy(person, {

    // get()方法用于进行获取值之前的操作
    get(target, property) {
        // target:目标对象
        // property:属性名
        
        //可以判断该属性是否存在,不存在默认输出default
        return property in target ? target[property] : "default"
    },
    
    // set()方法用于,为对象设置值之前的操作
    set(target, property, value) {
        // target:目标对象
        // property:属性名
        // value:设置的值
        
        // 可以对输入的数据做检测
        if (property === "age") {
            if (!Number.isInteger(value)) {
                throw new TypeError(`${value} is not an integer`)
            }
        }
        
        // 设置值
        target[property] = value
    },
    
    
    // 删除对象中的属性
    deleteProperty(target, property) {
        delete target[property]
    }
})

console.log(proxy.name) // Linda
console.log(proxy.xxx)  // default
proxy.gender = "f" 
console.log(person)  // { name: 'Linda', age: 22, gender: 'f' }
console.log(proxy)   // { name: 'Linda', age: 22, gender: 'f' }
console.log(person === proxy)  // false

delete proxy.name
console.log(person) // { age: 22, gender: 'f', class: '1A' }

proxy.age = "hahaha" // TypeError: hahaha is not an integer
  • 其他方法
    在这里插入图片描述

Reflect

  • Reflect 是一个内置对象
  • 提供拦截javascript操作的方法
  • Reflect不是一个函数对象,因此他是不可构造的

Reflect.get()

// Objectvar obj = { x: 1, y: 2 };
Reflect.get(obj, "x"); 
// 1

// Array
Reflect.get(["zero", "one"], 1); 
// "one"

Reflect.set()

  • Reflect.set(target, propertyKey, value[, receiver])
  • 在一个对象上设置一个属性
  • target:设置属性的目标对象。
  • propertyKey:设置的属性的名称。
  • value:设置的值。
  • receiver:如果遇到 setter,receiver则为setter调用时的this值。

// Objectvar obj = {};
Reflect.set(obj, "prop", "value"); // true
obj.prop; // "value"

// Arrayvar arr = ["duck", "duck", "duck"];
Reflect.set(arr, 2, "goose"); // true
arr[2]; // "goose"

// It can truncate an array.
Reflect.set(arr, "length", 1); // true
arr; // ["duck"];

// With just one argument, propertyKey and value are "undefined".
var obj = {};
Reflect.set(obj); // true
Reflect.getOwnPropertyDescriptor(obj, "undefined");// { value: undefined, writable: true, enumerable: true, configurable: true }

Reflect.setPrototypeOf()

  • Reflect.setPrototypeOf(target, prototype)
  • 可设置对象的原型(即内部的 [[Prototype]] 属性)为另一个对象或 null,如果操作成功返回 true,否则返回 false。
  • target:设置原型的目标对象。
  • prototype:对象的新原型(一个对象或 null)。
Reflect.setPrototypeOf({}, Object.prototype); // true

// It can change an object's [[Prototype]] to null.
Reflect.setPrototypeOf({}, null); // true

// Returns false if target is not extensible.
Reflect.setPrototypeOf(Object.freeze({}), null); // false

// Returns false if it cause a prototype chain cycle.
var target = {};var proto = Object.create(target);
Reflect.setPrototypeOf(target, proto); // false

Reflect.deleteProperty()

var obj = { x: 1, y: 2 };
Reflect.deleteProperty(obj, "x"); // true
obj; // { y: 2 }

var arr = [1, 2, 3, 4, 5];
Reflect.deleteProperty(arr, "3"); // true
arr; // [1, 2, 3, , 5]

// 如果属性不存在,返回 true
Reflect.deleteProperty({}, "foo"); // true

// 如果属性不可配置,返回 false
Reflect.deleteProperty(Object.freeze({foo: 1}), "foo"); // false

Reflect.ownKeys()

  • Reflect.ownKeys(target)
  • 返回一个由目标对象自身的属性键组成的数组
  • target:检查是否可扩展的目标对象。
Reflect.ownKeys({z: 3, y: 2, x: 1}); // [ "z", "y", "x" ]
Reflect.ownKeys([]); // ["length"]

var sym = Symbol.for("comet");
var sym2 = Symbol.for("meteor");
var obj = {[sym]: 0, "str": 0, "773": 0, "0": 0,
           [sym2]: 0, "-1": 0, "8": 0, "second str": 0};
           
Reflect.ownKeys(obj);
// [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]
// Indexes in numeric order, 
// strings in insertion order, 
// symbols in insertion order

Reflect.apply()

  • Reflect.apply( target, thisArgument, argumentsList )
  • 通过指定的参数列表,发起对目标函数的调用
  • target:目标函数
  • thisArgumenttarget:函数调用时绑定的this对象
  • argumentsListtarget:函数调用时传入的实参列表,该参数应该是一个类数组的对象。
Reflect.apply(Math.floor, undefined, [1.75]); 
// 1;

Reflect.apply("".charAt, "ponies", [3]);
// "i"

Reflect.construct()

Reflect.apply(Math.floor, undefined, [1.75]); 
// 1;

Reflect.apply("".charAt, "ponies", [3]);
// "i"

Reflect.defineProperty()

const student = {};
Reflect.defineProperty(student, "name", {value: "Mike"}); // true
student.name; // "Mike"

Reflect.getOwnPropertyDescriptor()

Reflect.getOwnPropertyDescriptor("foo", 0);
// TypeError: "foo" is not non-null object

Reflect.getOwnPropertyDescriptor({x: "hello"}, "x");
// {value: "hello", writable: true, enumerable: true, configurable: true}

Reflect.getOwnPropertyDescriptor({x: "hello"}, "y");
// undefined

Reflect.getOwnPropertyDescriptor([], "length");
// {value: 0, writable: true, enumerable: false, configurable: false}

Reflect.getPrototypeOf()

Reflect.getPrototypeOf({}); // Object.prototype
Reflect.getPrototypeOf(Object.prototype); // null
Reflect.getPrototypeOf(Object.create(null)); // null
Reflect.getPrototypeOf('foo')  // Throws TypeError

Reflect.has()

Reflect.has({x: 0}, "x"); // true
Reflect.has({x: 0}, "y"); // false

// 如果该属性存在于原型链中,返回true 
Reflect.has({x: 0}, "toString");

// Proxy 对象的 .has() 句柄方法
obj = new Proxy({}, {
  has(t, k) { return k.startsWith("door"); }});
Reflect.has(obj, "doorbell"); // true
Reflect.has(obj, "dormitory"); // false

Reflect.isExtensible()

var empty = {};
Reflect.isExtensible(empty); // === true 

Reflect.preventExtensions(empty); 
Reflect.isExtensible(empty); // === false 

var sealed = Object.seal({}); 
Reflect.isExtensible(sealed); // === false 

var frozen = Object.freeze({}); 
Reflect.isExtensible(frozen); // === false

Reflect.isExtensible(1);
// TypeError: 1 is not an object

Reflect.preventExtensions()

// Objects are extensible by default.var empty = {};
Reflect.isExtensible(empty); // === true

// ...but that can be changed.
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false

Reflect.preventExtensions(1);
// TypeError: 1 is not an object

Set

  • Set是一个类型
  • Set 内的值不允许重复
  • 添加已存在的值,该值会被忽略掉
/** 创建、添加 */
const s = new Set()
// add()方法返回Set对象,可以链式调用
s.add(3).add(6).add(54).add(45)
console.log(s)

// 打印结果
// Set { 3, 6, 54, 45 }
/** 遍历 */
const s = new Set()
s.add(3).add(6).add(54).add(45)

// forEach()方法
s.forEach(i => console.log(i))

// for...of...方法
for (let i of s) {
    console.log(i)
}
/** 常用方法 */
const s = new Set()
s.add(3).add(6).add(54).add(45)

// 获取长度
console.log(s.size) // 4

// 查询是否有指定值
console.log(s.has(45)) // true
console.log(s.has(100)) // false

// 删除指定值
console.log(s.delete(45)) // true
console.log(s) // Set { 3, 6, 54 }
console.log(s.delete(500)) // false

// 清空
s.clear()
console.log(s) // Set {}
/** 与数组交互 */
const arr = [3, 67, 3, 7, 4, 7, 5, 0]

// 为数组去重
const s = new Set(arr)
console.log(s) // Set { 3, 67, 7, 4, 5, 0 }

// Set转换为数组
console.log(Array.from(s)) // [ 3, 67, 7, 4, 5, 0 ]
console.log([...s]) // [ 3, 67, 7, 4, 5, 0 ]

Map

  • 和Object一样,都是键值对集合
  • 与Object不同的是,Object的键最终都会转为字符串类型
const m = new Map()
const person = {
    name: "Tom",
    age: 24,
}

//Map对象可以存放不同类型的键
m.set(person, "class A")
m.set(true, "123")
m.set(111, 222)
console.log(m) // Map { { name: 'Tom', age: 24 } => 'class A', true => '123', 111 => 222 }

// 遍历
m.forEach((value, key) => {
    console.log(key, value)
})

// get()方法
console.log(m.get(true)) // 123

// has()方法
console.log(m.has(person)) // true

// delete()方法
m.delete(111)
console.log(m) // Map { { name: 'Tom', age: 24 } => 'class A', true => '123' }

// clear()方法
m.clear()
console.log(m) // Map {}

Symbol

  • Symbol是个类型
  • 每创建一个Symbol都是独一无二的
  • 可以通过Symbol中的for()静态方法,与一个字符串相关联,并复用已有的Symbol
  • 主要用在Object中,可以避免对象属性名重复;也可以作为私有属性,禁止外界直接访问
  • 可以通过Object.getOwnPropertySymbols()获取所有Symbol属性
  • 可以改变对象的toString标签
const sy = Symbol()

// Symbol是个类型
console.log(typeof sy) // symbol

// 每个Symbol都是独一无二的
console.log(Symbol() == Symbol()) // false
console.log(Symbol() === Symbol()) // false

//可以通过Symbol中的for()静态方法,与一个字符串相关联,并复用已有的Symbol
const s1 = Symbol.for("example")
const s2 = Symbol.for("example")
console.log(s1 === s2) // true
// for() 会对传入的值自动toString()
console.log(Symbol.for(true) === Symbol.for("true")) // true

// 可以用在Object的属性名上
const obj = {
    [Symbol()]: "456"
}
obj[Symbol()] = "123"
console.log(obj) // { [Symbol()]: '456', [Symbol()]: '123' }

// 可以用在Object的私有属性上,外界无法直接访问
const name = Symbol()
const person = {
    [name]: "Linda",
    say: function () {
        console.log(`hello ${this[name]}, nice to meet you`)
    }
}
person.say() // hello Linda, nice to meet you

for (let item in person) {
    console.log(item)
}// normalKey say
console.log(Object.keys(person)) // [ 'normalKey', 'say' ]
console.log(JSON.stringify(person)) // {"normalKey":"normal"}

// 可以通过Object.getOwnPropertySymbols()获取所有Symbol属性
console.log(Object.getOwnPropertySymbols(person)) // [ Symbol() ]

//可以改变对象的toString标签
const obj1 = {}
console.log(obj1.toString()) // [object Object]
obj1[Symbol.toStringTag] = "myObj"
console.log(obj1.toString()) // [object myObj]

for…of 与 iterator

  • 使用for…of循环是以实现Iterable接口为前提
  • 数组、Set对象、Map对象都已实现了Iterable接口,而Object对象并没有,所以Object使用for…of循环会报错
    (数组)
    在这里插入图片描述

(Set对象)
在这里插入图片描述

(Map对象)
在这里插入图片描述

(Object对象)
在这里插入图片描述

for…of的工作原理

// 调用 被遍历对象的 迭代器Iterable
// 通过 迭代器的 next() 方法获取对象数据
const arr = [1,5,3,7]
const arrIterator = arr[Symbol.iterator]()

console.log(arrIterator.next()) // { value: 1, done: false }
console.log(arrIterator.next()) // { value: 5, done: false }
console.log(arrIterator.next()) // { value: 3, done: false }
console.log(arrIterator.next()) // { value: 7, done: false }
console.log(arrIterator.next()) // { value: undefined, done: true }
console.log(arrIterator.next()) // { value: undefined, done: true }

解析迭代器

  • Iterable : 可迭代接口,内部必须要有个用于返回迭代器的 iterator 方法
  • Iterator : 迭代器接口,内部必须要有个用于迭代的 next() 方法
  • IterationResult : 迭代结果接口,内部必须有 value属性 和 done属性

const obj = {

    store: ["as", "sd", "df", "fg"],
    
    [Symbol.iterator]: function () { // Iterable : 可迭代接口,内部必须要有个用于返回迭代器的 iterator 方法
    
        let idx = 0 // 循环对象下标
        let self = this // 使用闭包特性,将当前对象缓存
        
        return {
        
            next: function () { // Iterator : 迭代器接口,内部必须要有个用于迭代的 next() 方法
            
                let result = { // IterationResult : 迭代结果接口,内部必须有 value属性 和 done属性
                    value: self.store[idx],
                    done: idx >= self.store.length
                }
                
                idx++
                
                return result
            }
        }
    }
}

for (const item of obj) {
    console.log("for inner:", item)
}

// 打印结果
// for inner: as
// for inner: sd
// for inner: df
// for inner: fg

Generator生成器

  • Generator生成器也是实现了 Iterator接口
  • 使用 * 声明一个函数为Generator生成器函数
  • 使用 yield 关键词 暂停该函数的运行,并返回相关的值
  • Generator生成器函数返回的是Generator对象
  • 可使用 next() 方法 继续执行Generator函数,并传递参数、接受返回值
function* example() {
    console.log(11111)
    const param1 = yield 100
    console.log("param1:", param1)
    console.log(22222)
    const param2 = yield 200
    console.log("param2:", param2)
    console.log(33333)
    const param3 = yield 300
    console.log("param3:", param3)
}

const g = example()

console.log(g)
// Object [Generator] {} 

console.log(g.next(1))
// 11111
// { value: 100, done: false }

console.log(g.next(2))
// param1: 2
// 22222
// { value: 200, done: false }

console.log(g.next(3))
// param2: 3
// 33333
// { value: 300, done: false }

console.log(g.next(4))
// param3: 4
// { value: undefined, done: true }

ES2016 (ES7) 概述

Array.prototype.includes

  • 检查数组中是否包含指定元素
const arr = ["assd", 123, NaN, true]

//原始方式 indexOf()
console.log(arr.indexOf(true)) // 3
console.log(arr.indexOf(777)) // -1

// includes() 方法
console.log( arr.includes(true) ) // true
console.log( arr.includes(777) ) // false

指数运算符 **

// 原始方法
console.log( Math.pow(2, 10) ) // 1024

// ** 运算符
console.log( 2 ** 10 ) //1024

ES2017 (ES8) 概述

Object.values

  • 获取对象中的所有value
  • 返回数组
const person = {
    name: "Linda",
    age: 12,
    class: "class A",
    grade: "2",
    say: function () {
        console.log(`hello, I am ${this.name}!`)
    }
}

console.log(Object.keys(person)) // [ 'name', 'age', 'class', 'grade', 'say' ]
console.log(Object.values(person)) // [ 'Linda', 12, 'class A', '2', [Function: say] ]

Object.entries

  • 将对象中的每对key value,以数组的形式返回
const person = {
    name: "Linda",
    age: 12,
    class: "class A",
    grade: "2",
    say: function () {
        console.log(`hello, I am ${this.name}!`)
    }
}

console.log(Object.entries(person))
// [
//   [ 'name', 'Linda' ],
//   [ 'age', 12 ],
//   [ 'class', 'class A' ],
//   [ 'grade', '2' ],
//   [ 'say', [Function: say] ]
// ]

// 可以使用 for...of来循环
for (const item of Object.entries(person)) {
    console.log(item)
}
// [ 'name', 'Linda' ]
// [ 'age', 12 ]
// [ 'class', 'class A' ]
// [ 'grade', '2' ]
// [ 'say', [Function: say] ]

// 可以用于快速创建Map对象
const m = new Map( Object.entries(person) )

Object.getOwnPropertyDescriptors

  • 获取对象中,属性的完整描述信息
  • 配合着 Object.definedProperties() 来使用
const person = {
    name: "Linda",
    age: 12,
    class: "class A",
    grade: "2",
    get sayClass() { // 自定义 get 方法
        return `hello, I am ${this.name}, I am from ${this.class}`
    }
}
console.log(person.sayClass)
// hello, I am Linda, I am from class A

/** 使用 assign() 方法复制对象,不会改变 */
const person2 = Object.assign({}, person)
person2.name = "Tom" // 改变对象内的属性值
// 得到的依旧是原来的数据,因为assign()方法将get方法当做了普通属性来复制
console.log(person2)
// {
//   name: 'Tom',
//   age: 12,
//   class: 'class A',
//   grade: '2',
//   sayClass: 'hello, I am Linda, I am from class A'
// }
console.log(person2.sayClass)
// hello, I am Linda, I am from class A

/** 使用 getOwnPropertyDescriptors()获取对象属性完整信息,再用 definedProperties() 复制对象就会改变 */
const propDescrip = Object.getOwnPropertyDescriptors(person)
const person3 = Object.defineProperties({}, propDescrip)
person3.name = "Tom"
console.log(person3)
// {
//   name: 'Tom',
//   age: 12,
//   class: 'class A',
//   grade: '2',
//   sayClass: [Getter]
// }
console.log(person3.sayClass)
// hello, I am Tom, I am from class A

String.prototype.padStart / String.prototype.padEnd

  • 两个都是字符串填充方法
  • 规定指定的字符长度和填充符
const person = {
    name: "Linda",
    age: 12,
    class: "class A",
    grade: "2",
}
for (const [key, value] of Object.entries(person)) {
    console.log(`${key.padEnd(10, "-")} | ${value.toString().padStart(10, "*")}`)
}

// name------ | *****Linda
// age------- | ********12
// class----- | ***class A
// grade----- | *********2

在函数参数中添加尾逗号

  • 无实际功能上的改变
const person = {
    name: "Linda",
    age: 12,
    class: "class A",
    grade: "2",
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值