前端知识-ES6

283 阅读12分钟

ES6更新的内容主要分为以下几点

  • 表达式:声明、解构赋值
  • 内置对象:字符串扩展、数值扩展、对象扩展、数组扩展、函数扩展、正则扩展、Symbol、Set、Map、Proxy、Reflect
  • 语句与运算:Class、Module、Iterator
  • 异步编程:Promise、Generator、Async

-----------------------------------------------------------------

var、let、const之间的区别

1. var 

在ES5中,顶层对象的属性和全局变量是等价的,用var声明的变量既是全局变量,也是顶层变量

注意:顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象

2. let

letES6新增的命令,用来声明变量

用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效

3.const

const声明一个只读的常量,一旦声明,常量的值就不能改变

三者区别可以围绕下面五点展开:

  • 变量提升
  • 暂时性死区
  • 块级作用域
  • 重复声明
  • 修改声明的变量
  • 使用

作用域

  • 全局作用域 
  • 函数作用域:function() {} 
  • 块级作用域:{} 

作用范围

  • var命令在全局代码中执行
  • const命令let命令只能在代码块中执行

赋值使用

  • const命令声明常量后必须立马赋值
  • let命令声明变量后可立马赋值或使用时赋值

声明方法:varconstletfunctionclassimport

Symbol

symbol是一种全新的基础数据类型,表示是唯一的值。symbol的值通过symbol( )函数创建。

let onlyValue = Symbol();
typeof onlyValue;  // symbol

let onlyValue1 = Symbol(),
    onlyValue2 = Symbol();
    
onlyValue1 === onlyValue2  // false

ES6中数组新增了哪些扩展

  • 扩展运算符的应用
  • 构造函数新增的方法
  • 实例对象新增的方法
  • 数组的空位
  • 排序稳定性

ES6中对象新增了哪些扩展

  • 属性的简写 
  • 属性名表达式
  • super关键字
  • 扩展运算符的应用
  • 属性的遍历
  • 对象新增的方法

ES6中函数新增了哪些扩展

  • 参数
  • 属性 
  • 作用域
  •  严格模式 
  • 箭头函数 

ES6中新增的Set、Map两种数据结构怎么理解

一、Set

Setes6新增的数据结构,类似于数组,但是成员的值都是唯一的,没有重复的值,我们一般称为集合

Set本身是一个构造函数,用来生成 Set 数据结构

Set的实例关于增删改查的方法:

  • add()

  • delete()

  • has()

  • clear()

二、Map

Map类型是键值对的有序列表,而键和值都可以是任意类型

Map本身是一个构造函数,用来生成 Map 数据结构

Map 结构的实例针对增删改查有以下属性和操作方法:

  • size 属性
  • set()
  • get()
  • has()
  • delete()
  • clear()

怎么理解ES6中 Promise的?使用场景?

一、介绍

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise对象有以下两个特点。

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

二、用法

ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。

Promise构建出来的实例方法:

  • then()
  • catch()
  • finally()
  • all()
  • race()
  • allSettled()
  • resolve()
  • reject()
  • try()

1.then

then是实例状态发生改变时的回调函数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数

then方法返回的是一个新的Promise实例,也就是promise能链式书写的原因

getJSON("/data.json").then(function(json) {
  return json.post;
}).then(function(post) {
  // ...
});

2.catch

catch()方法是.then(null, rejection).then(undefined, rejection)的别名,用于指定发生错误时的回调函数

getJSON('/data.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 处理 getJSON 和 前一个回调函数运行时发生的错误
  console.log('发生错误!', error);
});

Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止

getJSON('/post/data.json').then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // some code
}).catch(function(error) {
  // 处理前面三个Promise产生的错误
});

3.finally

finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

4.all

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例

// 生成一个Promise对象的数组
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + ".json");
});

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});

5.race

const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);

p
.then(console.log)
.catch(console.error);

三、总结

promise解决异步操作的优点:

  • 链式操作减低了编码难度
  • 代码可读性明显增强

Promise对象是一个构造函数,用来生成Promise实例

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject

  • resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”
  • reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”

promise对象仅有三种状态

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)

附加: www.jb51.net/article/226…

解构赋值

1.对象

let obj = {
    names:'张三',
    age : 18,
    sex : '女',
    data :[1,2,3,4,5],
	details: {
        nickName: "光脚思考",
        address: "中国北京",
        signature: "勿以善小而不为,勿以恶小而为之"
    },
    say : function(){
        console.log('你好我是张三');
    }
}
// 1. 解构对象中的变量
let {names, age, status = "offline", details: { signature }, say} = obj;   
console.log(names, age, status, signature);
let {
        data : [a,b,c]
    } = obj;

// 2. 解构对象中的方法   
say();    

2.数组

let [a, b, d] = [1, [2, 3], 4];
console.info(a);
console.info(b);
console.info(d);

3.函数

function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

4.循环中的解构赋值

let users = [
    {
        userName: "光脚丫思考1",
        blog: "https://blog.csdn.net/gjysk",
    },
    {
        userName: "光脚丫思考2",
        blog: "https://blog.csdn.net/gjysk",
    }
];
for (user of users) {
    const { userName, blog } = user;
    let message = `大家好,我是${userName},博客地址是:${blog}`;
    console.info(message);
}

5.数值和布尔值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

附加:developer.mozilla.org/zh-CN/docs/…

Proxy

介绍和使用

Proxy 是 ES6 为了操作对象引入的 API 。

Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。

// 设 o 为房东,即被代理的对象
let o = {
  name: 'Faker',
  price: 200
}

// 设 d 为中介,即代理
let d = new Proxy(o, {})

console.log(d.price, d.name) // 200 'Faker'

// 因为传的是空对象,所以是透传

let d = new Proxy(o, {
  get(target, key) { // target 是指被代理的对象 o,key 指的是 o 的属性
    // 如果 key 为价格时进行加 10 的操作,否则返回 key 的值本身
    if (key === 'price') {
      return target[key] + 10
    } else {
      return target[key]
    }
  }
})

console.log(d.price, d.name) // 210 "Faker"

Proxy 实例的方法

handler解析

关于handler拦截属性,有如下:

  • get(target,propKey,receiver):拦截对象属性的读取
  • set(target,propKey,value,receiver):拦截对象属性的设置
  • has(target,propKey):拦截propKey in proxy的操作,返回一个布尔值
  • deleteProperty(target,propKey):拦截delete proxy[propKey]的操作,返回一个布尔值
  • ownKeys(target):拦截Object.keys(proxy)for...in等循环,返回一个数组
  • getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象
  • defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc),返回一个布尔值
  • preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值
  • getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象
  • isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值
  • setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值
  • apply(target, object, args):拦截 Proxy 实例作为函数调用的操作
  • construct(target, args):拦截 Proxy 实例作为构造函数调用的操作

1.get()

get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。

get方法的用法,上文已经有一个例子,下面是另一个拦截读取操作的例子。

var p = new Proxy(target, {
  get: function(target, property, receiver) {

  }
});

//target 目标对象  //property 获取的属性名  //receiver Proxy或者继承 Proxy 的对象

2.set()

set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。

const p = new Proxy(target, {
  set: function(target, property, value, receiver) {

  }
});

//target 目标对象  //property 将被设置的属性名或 Symbol。value 新属性值  //receiver最初被调用的对象。通常是 proxy 本身,但 handler 的 set 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。

3.has()

has()方法用来拦截HasProperty操作,即判断对象是否具有某个属性时,这个方法会生效。典型的操作就是in运算符。

var p = new Proxy(target, {
  has: function(target, prop) {

  }
});

//target 目标对象 //prop 需要检查是否存在的属性。

4.apply()

apply方法拦截函数的调用、callapply操作。

var p = new Proxy(target, {
  apply: function(target, thisArg, argumentsList) {

  }
});
//target 目标对象(函数) //thisArg 被调用时的上下文对象  //argumentsList 被调用时的参数数组。

Reflect

介绍

Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。

Reflect对象一共有 13 个静态方法。

  • Reflect.apply(target, thisArg, args)
  • Reflect.construct(target, args)
  • Reflect.get(target, name, receiver)
  • Reflect.set(target, name, value, receiver)
  • Reflect.defineProperty(target, name, desc)
  • Reflect.deleteProperty(target, name)
  • Reflect.has(target, name)
  • Reflect.ownKeys(target)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, name)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)

静态方法

get( )

查找并返回target对象的name属性,如果不存在此属性则返回undefined。如果target对象制定了getter,则receiver为getter指定的this值。第一个参数不是对象则报错。

let testObject = {
    foo: 1,
    bar: 2,
    get baz() {
        return this.foo + this.bar;
    }
}

let testReceiverObject = {
    foo: 3,
    bar: 4
}

Reflect.get(testObject, 'foo');  // 1
Reflect.get(testObject, 'baz');  // 3
Reflect.get(testObject, 'baz', testReceiverObject);  // 7
Reflect.get(1, 'baz');  // TypeError: Reflect.get called on non-object

set()

设置target对象的name属性等于value。如果name属性设置了赋值函数,则赋值函数的this绑定receiver。第一个参数不是对象则报错。

let testObject = {
    foo: 1,
    set bar(value) {
        return this.foo = value;
    }
}

let testReceiverObject = {
    foo: 3
}

Reflect.set(testObject, 'foo', 4);  // foo: 4
Reflect.set(testObject, 'bar', 4);  // foo: 4
Reflect.set(testObject, 'foo', 1, testReceiverObject);  // foo: 1
Reflect.set(1, foo);  // TypeError: Reflect.set called on non-object

类(class)

class 的本质是 function。

它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法

class Example {
  a = 3;
  constructor() {
    console.log(this.a);
  }
}
new Example()

模块化(Module)

ES5不支持原生的模块化,在ES6中模块作为重要的组成部分被添加进来。模块的功能主要由 export 和 import 组成。每一个模块都有自己单独的作用域,模块之间的相互调用关系是通过 export 来规定模块对外暴露的接口,通过import来引用其它模块提供的接口。同时还为模块创造了命名空间,防止函数的命名冲突。

由于 ES6 模块是编译时加载,使得静态分析成为可能。有了它,就能进一步拓宽 JavaScript 的语法,比如引入宏(macro)和类型检验(type system)这些只能靠静态分析实现的功能。

除了静态加载带来的各种好处,ES6 模块还有以下好处。

  • 不再需要UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。目前,通过各种工具库,其实已经做到了这一点。
  • 将来浏览器的新 API 就能用模块格式提供,不再必须做成全局变量或者navigator对象的属性。
  • 不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供。

导出(export)

1.导出变量

//test.js 1
export var name = 'zhangsan' 

//test.js 2
var name = 'Rainbow';
var age = '24';
export {name, age};

2.导出函数

// moduleA.js
export function myModule(someArg) {
  return someArg;
}  

导入(import)

import {myModule} from 'myModule';// main.js
import {name,age} from 'test';// test.js

异步遍历器

介绍

异步遍历器是为解决同步遍历器 (iterator) 无法实现异步操作效果而产生的一种特殊遍历方式,主要区别与同步遍历器的地方在于 value 和 done 都是异步产生的,调用 next( ) 方法返回的是一个 promise 对象。

使用 then( ) 获取 promise 对象变成 resolve 以后的回调函数,该回调函数的参数是具有 value 和 done 两个属性的对象。

for await...of

在同步遍历器中使用 for...of 循环,在异步遍历器中使用 for await...of 进行循环,不过 for await...of 也可以用于同步遍历器。

async function test() {
  for await (let i of asyncIteratorTest(['a', 'b'])) {
    console.log(i);
  }
}

异步 Generator 函数

异步的 Generator 函数返回的是一个 异步遍历器 对象。

async function* test() {
  yield 'test';
}
const testObj = test();
testObj.next().then(item => {
  console.log(item);
})

es6.ruanyifeng.com/

www.es6.maple.ink/