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

你不知道的ECMAScript6 #9

Open
hawx1993 opened this issue Apr 25, 2017 · 0 comments
Open

你不知道的ECMAScript6 #9

hawx1993 opened this issue Apr 25, 2017 · 0 comments

Comments

@hawx1993
Copy link
Owner

hawx1993 commented Apr 25, 2017

编译时加载

ES6模块不是对象,而是通过export命令显式指定输出的代码,输入时也采用静态命令的形式。


// ES6模块

import { stat, exists, readFile } from 'fs';

上面代码的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”,即ES6可以在编译时就完成模块加载,效率要比CommonJS模块的加载方式高。当然,这也导致了没法引用ES6模块本身,因为它不是对象。

函数

默认参数

可以直接在默认参数中调用函数,但当函数提供实参时,默认参数并不会直接调用函数,而是使用实参:

function addValue(a,b){
	return a+b;
}
function add(a,b=addValue(1,2)){
	return a+b;
}
console.log(add(1,2));//3
console.log(add(1));//4

function foo(x = 3) {
    console.log( x );
}
foo();                    // 3
foo( undefined );        // 3
foo( null );            // null
foo( 0 );                // 0

ES6函数参数变量是默认声明的,所以不能用let或const再次声明。默认参数只有当传入的值是undefined时,才会生效

剩余参数rest和扩展运算符

一个函数只能有一个剩余参数,且必须放在最后面。设计剩余参数的目的是用来替代 ECMAScript 中的 arguments。

扩展运算符好比rest的逆运算,用于将数组转为用逗号分隔的参数序列,而剩余参数允许你把多个独立的参数整合到一个数组中。
rest参数的形式为:...变量名;扩展运算符是三个点(...

比如,在使用Math.max计算一个数组中最大的数:

let value = [1,10,100,-1000];
Math.max.apply(null,value);//100

//使用扩展运算符
console.log(Math.max(...value));//100

args 无论是不是空的,它永远是一个数组。但它不包含已经命名的 x,y 和 z 参数,只会包含超出前三个值的传入参数。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中:

function foo(x,y,z,...args) {
    console.log( x, y, z, args );
}

foo();                    // undefined undefined undefined []
foo( 1, 2, 3 );            // 1 2 3 []
foo( 1, 2, 3, 4 );        // 1 2 3 [ 4 ]
foo( 1, 2, 3, 4, 5 );    // 1 2 3 [ 4, 5 ]

function bar(...args) {
    console.log( args[3] );//4
    console.log(args);//[1, 2, 3, 4, 5]
}

var arr = [ 1, 2, 3, 4, 5 ];
bar( ...arr ); 
bar( arr );// args =>  [[1,2,3,4,5]]; ...args => [1,2,3,4,5]

在形参列表,它把实参整合。在实参列表,它把实参展开。

扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。扩展运算符用于对象中,等同于Object.assign()

let obj = {name: 'trigkit4', age: 23}; 
console.log({...obj});// {name: 'trigkit4', age: 23}

rest参数和arguments对象的区别

-rest参数只包含那些没有对应形参的实参;而 arguments 对象包含了传给函数的所有实参。

  • arguments 对象不是一个真实的数组;而rest参数是真实的 Array 实例。

  • arguments 对象对象还有一些附加的属性 (比如callee属性)。

解构赋值

解构也可以设置默认值:

const getUserName = () => {
  return {
         name1: 'mike',
         name2: 'jake'
    };
};
const {name1, name3 = 'trigkit4'} = getUserName();
name3;//trigkit4
//结构数组可跳过其中某几项
const browserSet = ['chrome','safari','firefox','edge'];
const [b1,b2,,b3] = browserSet;
b1;//chrome
b3;//edge

//设置默认值
function getAges(
    {age1=10,age2=20} = {}
){
    console.log(age1,age2)
}
getAges({});//10 20


function getAge(
    {age1,age2} = {age1:1,age2:2}
){
    console.log(age1,age2)
}
getAge();//1,2
getAge({});//undefined undefined
getAge({age1:3});//3 undefined

new Set与数组去重

Set 内无重复的值

const arr = [...new Set([1, 2, 3, 3, NaN, NaN])]
// [1, 2, 3, NaN]  

对象字面量

const name = 'Jane';
const age = 20

const person = {
  [name]: true,
  [age]: true
}
//Object {20: true, Jane: true}

箭头函数

箭头函数不属于普通的 function,所以没有独立的上下文。箭头函数没有它自己的this值,箭头函数内的this值继承自外围作用域(如果没有就是全局)。如果你在箭头函数中使用了this,那么该this一定就是外层的this。箭头函数会继承当前上下文的 this 关键字。

const person = {
    name: 'trigkit4',
    getName: () => this.name
}

// 编译结果却是
'use strict';

var person = {
    name: 'trigkit4',
    getName: function getName() {
        return undefined.name;
    }
};

该箭头函数的外层作用域是window对象,在ES6中,会默认采用严格模式,因此this也不会自动指向window对象了,而箭头函数本身并没有this,因此this就只能是undefined

在以下场景中不要使用箭头函数去定义:

-定义对象方法、定义原型方法、定义构造函数、定义事件回调函数。

箭头函数没有arguments对象,但可以使用rest参数:

let fn = (a,b) =>{
	console.log(arguments)
}
fn(1,2);//arguments is not defined

let fn = (...args) =>{
	console.log(...args)
}
fn(1,2);//1 2

箭头函数会继承当前上下文的 this 关键字

//例如:
    [1,2,3].map( x => x + 1 )

//等同于:
    [1,2,3].map((function(x){
        return x + 1
    }).bind(this))

import 和require

import 不能和 module.exports 一起用,能用的话就可以修改 export 的内容了。

  • import必须放在文件最顶部,require不需要;
  • import和export最终会被babel编译成requiremodule.exports。所以import一个文件的时候,是同步的。会按照import顺序输出该值。
  • CommonJS允许你动态加载模块,es6不允许。

let和const

let不会向window分配任何内容:

let me = "go";  // 全局作用域
console.log(window.me); //undefined

const

const是只读变量。const 对象仍然可以被改变的。

const abc = {a: 'a'};
abc.a = 'b';
console.log(abc);//Object {a: "b"}

Promise

如果一个 promise 失败,all和race也将 reject(拒绝)。

var p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("1"), 1001)
})
var p2 = new Promise((resolve, reject) => {
  setTimeout(() => reject("2"), 1)
})
 
Promise.race([p1, p2]).then((res) => {
   console.log("success" + res)
}, res => {
   console.log("error " + res)
})
 
Promise.all([p1, p2]).then((res) => {
   console.log("success" + res)
}, res => {
   console.log("error " + res)
})
//error 2
//error 2

Generator 函数

Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。

var go = function*(){  
    yield 1;  
    yield 2;  
    yield 3;  
  };  
[...go()] // [1, 2, 3] 

for...of循环可以使用的范围包括数组、Set 和 Map 结构、类数组对象(比如arguments对象、DOM NodeList 对象)以及 Generator 对象和字符串

@hawx1993 hawx1993 changed the title 你不知道的es6 你不知道的ECMAScript6 Apr 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant