ES6进修总结(1)

半个月前就决议要将ES6的进修总结一遍,效果迁延症一犯,半个月就过去了,现在补起来,忸捏忸捏。

阮一峰的《ES6规范入门》这本书有300页摆布,除了几个新的API和js语法的扩大,真正有价值的内容并不多。所谓“存期近合理”,每部份的内容都对响应的人群有价值,我将连系我在练习中打仗过的ES6的部份和我的个人明白来对这本书的内容做个总结。若有不足或许错误指出,还请拍砖。

总结重要从三个方面睁开:1. 语法扩大;2. ES6新API; 3. 模块化计划。

1. 语法扩大

(1)let、const与块级作用域

  • let、const声明的标识符仅在块级作用域内有效,块级作用域就是大括号({})包括的地区。const与let的差异在于let声明的是变量,const声明的是常量。

  • let、const不存在变量提拔

// let/const不存在变量提拔
console.log(foo);   // undefined
var foo = "abc";

console.log(lish);  // 未定义报错,ReferenceError
let lish = "hello";
  • let、const暂时性死区:已声清楚明了变量,在声明变量之前,该变量都是不可用的。在部分作用域中,纵然已存在全局的同名变量,照样没法在部分声明之前接见该变量,有点绕,直接上代码。

// 暂时性死区
var num = 1;
const add = () => {
    console.log(num);
    let num;
}
add();      // 报错,num is not defined
  • let、const不许可反复声明,在ES5中,用var声明的变量我们能够用var反复声明,就好像从新赋值一样,然则用let、const反复声明会报错。

(2)解构赋值

解构赋值说白了就是“情势婚配”,从等号双方对应的位置掏出对应的值

  1. 数组的解构赋值

let [a, b, c] = [1, 2, 3];
// 从对应位置拿出对应值,相当于我们声清楚明了三个变量
// let a = 1, b = 2, c = 3;

须要指出一点,只需某种数据具有Iterator接口,就能够采纳数组情势的解构赋值(其中就包括字符串),Iterator我们会在总结(2)提到。 举个例子

// Set是ES6新增的一种数据范例,具有Iterator接口
let [x, y, z] = new Set([1, 2, 3]); // x = 1, y = 2, z = 3

解构许可指定默认值。默认值有undefined触发

let [x = 1, y = 2] = [44]; // x = 44, y = 2;
let [x = 1, y = 2] = [44, undefined]; // 与上面等价
  1. 对象的解构赋值

只需我们晓得这是情势婚配,就比较好明白了,先经由过程键找到对应的值,将值赋给等式左侧雷同键名对应的变量,{foo}就是{foo: foo}的简写情势,这属于对象的扩大,接下来会提到。

let { foo, bar } = { foo: 'hello', bar: 'world' };  // foo = 'hello', bar = 'world'
let {foo: val, bar} =  { foo: 'hello', bar: 'world' };  // val = 'hello', bar = 'world';

和数组解构相似,也可认为对象解构赋默认值let {x = 3} = {};,默认值由undefined触发。
须要注重的一点是,大括号不能涌现在行首,会被剖析为代码块,比方{x} = {x: 1};

  1. 函数参数的解构赋值

参数可认为数组或对象
比方:我们为函数直接传一个数组,在函数内部我们直接能够运用解构后的值

const add = ([x, y]) => {
    return x + y;
}
console.log(add([1, 2]);    // 3
console.log(add.length);    // 1

上面代码中,比较好明白的是add.length,代表函数参数的个数,然则我们为参数指定默认值时, length为0,缘由就是函数的length属性为没有指定默认值的参数的个数,而且不包括rest参数

const add = ([x, y] = [0, 0]) => {
    return x + y;
}
console.log(add());    // 0
console.log(add.length);    // 0

(3)模板字符串

字符串扩大中,最有效的就是模板字符串,用反引号(`)标识,模板字符串中能够运用变量,省去了用连接符来拼接字符串的贫苦。

let foo = 'hello';
console.log(`${foo} world!`);   // hello world

看了上面,置信人人都会在模板字符串中运用变量了,就是讲变量写在${}中就行了。
别的,模板字符串中还能够运用表达式(包括函数挪用,运算等),一样,将表达式写在${}中就行了。

(4)扩大运算符(…)与 rest参数

  1. 扩大运算符
    作用:将一个数组(权且先说是数组)转换为用逗号分开的参数序列。

console.log([1, 2, ...[2, 3, 4]]); // [1, 2, 2, 3, 4]
console.log(...'hello'); // h e l l o

// generator函数
let go = function* () {
    yield 1;
    yield 2;
    yield 3;
};
console.log(...go());   // 1 2 3

题目来了:扩大运算符能够作用于哪些数据范例呢?

回复这个题目很症结,直接说答案吧:具有Iterator接口的数据范例

  1. rest参数

阮大神的书上原话:rest参数(…变量名),用于猎取函数过剩的参数,放进一个数组中。

const add = function (arg1, ...values) {
    return values;
};
console.log(add(1, 3, 5, 7));   // [3, 5, 7]

个人之见,这句话有点题目,rest参数好比是扩大运算符的逆运算,怎么能只用于猎取函数过剩的参数呢,事实证实,rest不单单议用于猎取函数参数。
我们看上的函数定义部份的参数和函数挪用部份的参数,这不就是一个情势婚配吗?arg1对应第一个参数,…values对应盈余的参数。说道情势婚配,不得不说解构赋值,那末我们在解构赋值中运用rest参数呢,下面我们碰运气

let values, num;
[num, ...values] = [1, 3, 5, 7];
console.log(values);    // [3, 5, 7]

试验证实rest参数也能够用于解构赋值中,要注重的是rest参数只能放在其他参数的背面,不然rest参数没法推断内里参数的个数

(5)数组的扩大

  1. Array.from()
    作用: 将相似数组的对象和可遍历的对象(具有Iterator接口)转为真正的数组

所谓相似数组的对象,症结在于有无一个length属性示意对象中属性的个数

var obj = {0: 'hello', 'sayName': 'hi', 1: 'world', length: 2};
console.log(Array.from(obj));   //['hello', 'world'];

上面转换的只是键名为数字的属性

  1. Array.of()
    作用:将一组数值转换为数组,重要目的为了填补Array组织函数不能辨认长度照样值。

  2. 实例要领find()和findIndex()
    find()找到第一个相符前提的数组成员,参数为函数,返回true示意找到

findIndex(),与find()相似,返回的是数组的索引。

  1. 遍历要领entries()、keys()、values()
    都返回遍历器对象,便利器对象可用for…of举行遍历

for(let index of ['a', 'b'].keys()) {
    console.log(index);
}
// 0
// 1

for(let value of ['a', 'b'].values()) {
    console.log(value);
}
// a
// b

for(let [index, value] of ['a', 'b'].entries()){
    console.log(index, value);
}
// 0 a
// 1 b
  1. includes()
    作用:推断数组是不是包括某个值,属于ES7,客户端运用要运用Babel举行转码,为了填补indexOf()的不足,indexOf()内部运用“===”举行推断,关于NaN的推断会失足,而includes()处置惩罚了这个题目

console.log([NaN, NaN].indexOf(NaN));   // -1
console.log([NaN, NaN].includes(NaN));  // true

(6)函数的扩大

函数参数的解构赋值,默认值在第一部份已提到,这里就不再总结,在函数扩大这一部份,我重要总结箭头函数的运用
ES6中能够运用箭头函数定义函数,体式格局以下:

const f = (arg1) => {
    return arg1 * 2;
}
const f = arg1 => arg1*2;     // 等同于上面的定义

当参数只要一个时,能够省略括号,当函数体只要return语句一条语句时,能够省略大括号和return症结字

运用箭头函数须要注重的几点

  1. 箭头函数不能够当作组织函数

  2. 不能够运用arguments对象

  3. 不能够运用yield敕令,不能用作generator函数

箭头函数没有本身的this,致使内部的this就是外层代码的this,所以不能用作组织函数,也不能运用call()、apply()、bind()转变this的指向

(7)对象的扩大

  1. 属性的简约示意法

变量名转属性名

let foo = 'hello';
let obj = {foo: foo};

// 简写情势
let foo = 'hello';
let obj = {foo};    // 变量名直接转为属性名

要领的简写

let obj = {
    sayName: function() {
        return 'hello';
    }
}

// 简写情势
let obj = {
    sayName() {
        return "hello";
    }
};
  1. ES6许可字面量定义对象时运用表达式作为对象的属性名
    将表达式放在中括号中,然则属性名表达式与简约示意法不能同时运用

let obj = {
    ['a' + 'bc']: 123
}
  1. Object.is()
    用来比较两个值是不是严厉相称,与“===”行动基础一致,不同之处在于: +0不即是-0,NaN即是本身

  2. Object.assign()
    将源对象的一切可罗列的自有属性复制(浅复制)到目的对象Object.assign(target, source1, source2 ...),返回target,能够处置惩罚数组,将其视为对象

let target = {a: 1};
let source1 = {b: 2};
let source2 = {c: 3};
Object.assign(target, source1, source2);
// target => {a: 1, b: 2, c: 3};

平常情况下,我们不愿望转变对象,只愿望兼并对象的属性,那末能够将target设为空对象{}, Object.assign({}, source1, source2);

须要注重的是Object.assign()实行的是浅复制, 假如源对象的属性为援用范例,那末target中对应的属性和源对象中的属性援用同一个值

let source1 = {b: {test: 'hello world'}};
let target = Object.assign({}, source1);

console.log(target.b);  // { test: 'hello world' }

source1.b.test = 111111;
console.log(target.b);  // {test: 111111}
  1. 对象的属性的遍历

for...in 轮回遍历对象本身和继续的可罗列属性(不含Symbol属性),Symbol是ES6中的一种新的数据范例,示意一个举世无双的值,在第二大部份,我将会讲到这个范例。
Object.keys(obj) 返回数组,包括对象本身的一切可罗列属性(不含Symbol属性)
Object.getOwnPropertyNames(obj) 返回数组,包括对象本身的一切属性(包括不可罗列属性,不包括Symbol属性)

说白了,就是ES5中遍历要领都没法猎取到Symbol属性

Object.getOwnPropertySymbols(obj)返回数组,包括本身的一切Symbol属性
Reflect.ownKeys(obj)返回一个数组,包括对象本身的一切属性(包括不可罗列和Symbol), Reflect是ES6中的新API,其目的之一就是将Object对象上一些属于言语层面的要领放到该对象身上,并修正某些要领,让其变得更合理。
Reflect.enumerate(obj)返回一个Iterator对象,遍历对象本身和继续的一切可罗列属性(不含Symbol),与for…in雷同

  1. __proto__和Object.setPrototype()

在红宝书中就已提到过__proto__属性,示意的是援用范例实例的一个内部指针,指向该实例的组织函数的原型对象。平常不发起我们直接运用,由于这是一个非规范属性,然则一切浏览器都布置了这个属性,node中也能够运用

// 应用__proto__完成继续
function Animal(name) {
    this.name = name;
}
Animal.prototype.sayName = function() {
    console.log(this.name);
};

function Dog(name, leg) {
    Animal.call(this, name);
    this.leg = leg;
}
Dog.prototype.__proto__ = Animal.prototype;
Dog.prototype.constructor = Dog;

var dog = new Dog("Genkle", 4);
dog.sayName();  // Genkle

Object.setPrototype(object, prototype)用于设置一个对象的prototype对象,相当于object.__proto__ = prototype,是ES6中设置原型对象的要领。

    原文作者:HarderK
    原文地址: https://segmentfault.com/a/1190000008994750
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞