Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 知识点整理 #34

Open
hsipeng opened this issue Mar 9, 2018 · 0 comments
Open

ES6 知识点整理 #34

hsipeng opened this issue Mar 9, 2018 · 0 comments

Comments

@hsipeng
Copy link
Owner

hsipeng commented Mar 9, 2018

ES6

什么是ES6

ECMAScript 标准的历史版本分别是 1、2、3、5。

ES4 太过激进,被废止。

ES5

Object.create() 、 Object.defineProperty() 、
.map() 、 .filter() …

ES6

箭头函数、字符串插值、代理、生成器..
Map 、 Set对象

迭代器和 for - of 循环

for - in 为普通对象遍历自身属性
forEach 不能 break

for - in 正确遍历数组、切能响应 break 、 continue 和 return

Symbol 对象 、 独有不冲突

迭代器对象

生成器

生成器是迭代器。所有的生成器都有内建.next()和 Symbol.iterator方法的实现。你只须编写循环部分的行为

function* range(start, stop) {
  for (var i = start; i < stop; i++)
yield i; 
}

模板字符串

与普通字符串不同的是,模板字符串可以多行书写.模板字符串中所有的空格、新行、缩进,都会原样输出在生成的字符串中

不定参数和默认参数

不定参数

ES6 提供了一种编写可 变参函数的新方式

arguments 对象

ES5

function containsAll(haystack) {
for (var i = 1; i < arguments.length; i++) {
  var needle = arguments[i];
  if (haystack.indexOf(needle) === -1) {
    return false;
  }
}
return true;
}

ES6

function containsAll(haystack, ...needles) {
  for (var needle of needles) {
    if (haystack.indexOf(needle) === -1) {
     return false;
		} 
	}
  return true;
}

默认参数

没有默认值的参数隐式默认为 undefined
传递 undefined 值等效于不传值

解构 Destructuring

数组解构赋值

[ variable1, variable2, ..., variableN ] = array;

被解构的值需要被强制转换为对象。大多数类型都可以被转换为对象, 但 null 和 undefined 却无法进行转换。当使用数组赋值模式时,被解构的值一定要包含 一个迭代器。

默认值

解构的实际应用

  • 函数参数定义

设计一个 对象作为参数,然后将不同的实际参数作为对象属性,以避免让 API 使用者记住 多个参数的使用顺序.

  • 配置对象参数

给需要解构的对象属性赋予默认值

  • 与 ES6 迭代器协议协同使用
var map = new Map();
map.set(window, "the global");
map.set(document, "the document");
for (var [key, value] of map) {
  console.log(key + " is " + value);
}
  • 多重返回值
function returnMultipleValues() {
  return [1, 2];
}
var [foo, bar] = returnMultipleValues();

箭头函数 Arrow Functions

// ES5
var total = values.reduce(function (a, b) {
return a + b;
}, 0);
// ES6
var total = values.reduce((a, b) => a + b, 0);

箭头的{被解析为块的开始,而不是对象的开始

// 为与你玩耍的每一个小狗创建一个新的空对象
var chewToys = puppies.map(puppy => {}); // 这样写会报 Bug! var chewToys = puppies.map(puppy => ({})); //

箭头函数没有它自己的 this 值,箭头函数内的 this 值继承自外围作用域

通过 object.method()语法调用的方法使用非箭头函数定义,这些函数需要从调用者 的作用域中获取一个有意义的 this 值。

// ES6 {
  ...
  addAll: function addAll(pieces) {
    _.each(pieces, piece => this.add(piece));
  },
... }

更简洁的对象字面量

// ES6 的方法语法 {
  ...
  addAll(pieces) {
    _.each(pieces, piece => this.add(piece));
  },
...}

Symbols

第七种基本类型

symbol 是程序创建并且可以用作属性键的值,并且它能避免命名冲突的风险。

Undefined 未定义
Null 空值
Boolean 布尔类型
Number 数字类型
String 字符串类型
Object 对象类型
var mySymbol = Symbol();
obj[mySymbol] = "ok!"; // 保证不会冲突
console.log(obj[mySymbol]); // ok!

获取 symbol 的三种方法

  • 调用 Symbol()
  • 调用 Symbol.for(string)
  • 使用标准定义的 symbol,例如:Symbol.iterator

集合

  • Set
  • Map
  • WeakMap 和 WeakSet
WeakMap 只支持 new、has、get、set 和 delete。 
WeakSet 只支持 new、has、add 和 delete。
WeakSet 的值和 WeakMap 的键必须是对象。

代理 Proxies

对象

对象是在 JS 程序中拥有[[Get]]、[[Set]]等操作的实体

  • 对象都有属性。你可以 get、set 或删除它们或做更多操作。
  • 对象都有原型。这也是 JS 中继承特性的实现方式。
  • 有一些对象是可以被调用的函数或构造函数

ECMAScript 标准委员会定义了一个由 14 种内部方法组成的集合ECMAScript 2015 Language Specification – ECMA-262 6th Edition,你可以调用、删除或 覆写普通方法,但是无法操作内部方法。

代理(Proxy)
它可以接受两个参数:目标对象(target)与句柄对象(handler)

var target = {}, handler = {};
var proxy = new Proxy(target, handler);

类 Class

let 和 const

let 是更完美的 var

  • let 声明的变量拥有块级作用域
  • let 声明仍然保留了提升的特性,但不会盲目提升
  • let声明的全局变量不是全局对象的属性
  • 形如for (let x...)的循环在每次迭代时都为x创建新的绑定
  • et 声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在到 达之前使用该变量会触发错误。
  • 用 let 重定义变量会抛出一个语法错误(SyntaxError)

const

const 声明的变量只可以在声明时赋值,不可随意修改,否则会导致 SyntaxError(语法错误)。

ES6 添加了块作用域, for 循环作用域,新的全局 let 作用域,模块作用域,以及求参数的默认值时使用的附加 作用域。

子类 Subclassing

原型继承,即使在 JavaScript 中类继承 的本质也是原型继承)的近类函数

如果不希望创建出来的实例继承自 Object.prototype,你甚至可以在 extends 后使用 null 来进行声明。

Super 属性

子类化内建方法

派生类构造函数

当我们执行基类的构造函 数前,this 对象没有被分配,从而我们无法得到一个确定的 this 值。因此,在子类的 构造函数中,调用 super 构造函数之前访问 this 会触发一个引用错误 (ReferenceError)。

new.target

class foo {
    constructor() {
       return new.target;
    }
}
class bar extends foo {
// 为了清晰起见我们显式地调用 super。 // 事实上不必去获取这些结果。 constructor() {
super(); 
}
}
// 直接调用 foo,所以 new.target 是 foo
new foo(); // foo
// 1) 直接调用 bar,所以 new.target 就是 bar
// 2) bar 通过 super()调用 foo,所以 new.target 仍然是 bar new bar(); // bar

我们新添加的元属性 new.target 与构造函数有关,因为直接通过 new 来 调用,所以它是一个被调函数,在这个函数中调用 super 会传递 new.target 的值

模块 Modules

export

export 列表可以在模块文件最外层作用域的每一处声明,不一定非要把它放在模 块文件的首行。你也可以声明多个 export 列表,甚至通过其它的 export 声明打造一个 混合的 export 列表,只要保证每一个被导出的名称是唯一的即可。

重命名 import 和 export

 // suburbia.js
// 这两个模块都会导出以`flip`命名的东西。
// 要同时导入两者,我们至少要将其中一个的名称改掉。 import {flip as flipOmelet} from "eggs.js"; import {flip as flipHouse} from "real-estate.js";

Default exports

let myObject = {
  field1: value1,
  field2: value2
};
export {myObject as default};
           

简略的表达方法

export default {
  field1: value1,
  field2: value2
};

关键字 export default 后可跟随任何值:一个函数、一个类、一个对象字面量, 只要你能想到的都可以。

模块对象

import * as cows from "cows";

当你 import *时,导入的其实是一个模块命名空间对象,模块将它的所有属性都 导出了。所以如果“cows”模块导出一个名为 moon()的函数,然后用上面这种方法“cows” 将其全部导入后,你就可以这样调用函数了:cows.moo()。

聚合模块

当你通知 JS 引擎运行一个模块时,它一定会按照以下四个步骤执行下
去:
语法解析:阅读模块源代码,检查语法错误。
加载:递归地加载所有被导入的模块。这也正是没被标准化的部分。
连接:每遇到一个新加载的模块,为其创建作用域并将模块内声明的所有绑定填充
到该作用域中,其中包括由其它模块导入的内容。
如果你的代码中有 import {cake} from "paleo"这样的语句,而此时“paleo”模块
并没有导出任何“cake”,你就会触发一个错误。这实在是太糟糕了,你都快要运行模块 中的代码了,都是 cake 惹的祸!
运行时:最终,在每一个新加载的模块体内执行所有语句。此时,导入的过程就已 经结束了,所以当执行到达有一行 import 声明的代码的时候......什么都没发生!

实用特性

  • Object.assign(target, ...sources)。一个新的标准库函数,与 Underscore 中的 _.extend()类似。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant