es6学习笔记(一)

1、 es6是什么?

es6全称ECMAScript 6。ECMAScript 和 JavaScript 之间的关系,前者是后者的规格,后者是前者的一种实现。 ES6一般是指 ES2015 标准。

 

2、 let和const声明变量

之前使用var关键字声明变量,无论声明在何处,都会被视为声明在{}大括号内的代码的最顶部(不在大括号内{}即在全局作用域的最顶部)。这就是函数变量提升。

function fun () {

    if (bool) {

        var test = 'hello man';

    } else {

        console.log(test)

    }

}

 

上面的代码实际上是:

function fun() {

    var test;

    if (bool) {

        test = 'hello man';

    } else {

        //此处访问test,值为undefined

        console.log(test);

    }

    //此处访问test,值为undefined

}

 

无论bool的值是true还是falsetest变量都会被声明。

 

1) let声明变量

let命令实际上为JavaScript新增了块级作用域。let命令声明的变量只在它所在的代码块内有效。

先看下面这一段代码:很显然只能输出十次10。

var funcs = [];

for (var i = 0; i < 10; i++) {

    funcs.push(function () {

        console.log(i)

    });

}

 

     那么如何依次输出0-9呢?

     ·闭包

for (var i = 0; i < 10; i++) {

    func.push((function (value) {

        return function () {

            console.log(value)

        }

    }(i)));

}

 

·let声明变量

for (let i = 0; i < 10; i++) {

    func.push(function () {

        console.log(i)

    })

}

 

变量ilet声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,因此能够依次输出0-9。

使用let声明变量的话,不存在变量提升的情况,必须在声明以后才使用,否则会报错,这在语法上称为“暂时性死区”。并且let不允许在相同作用域内重复声明变量。

 

2) const声明变量

const声明的变量是一个只读变量,一旦声明就必须马上初始化并且不能改变值,因此如果用const只声明而不赋值也会报错。

const的作用域与let相同,只在当前的块级作用域内有效。同样的,也不能变量提升,存在暂时性死区,不能重复声明。

本质:

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

 

3、 变量的解构赋值

1) 数组的解构赋值

[基本用法]

let [a, b, c] = [1, 2, 3];

上面代码表示。可以从数组中提取值,按照对应位置,给变量赋值。

本质上,这种写法属于“模式匹配”,只要等号两边模式相同,左边的变量就会被赋予对应的值。

 

如果解构不成功,变量的值就等于undefined。

let [foo] = [];
foo //undefined

let [bar, foo] = [1];
foo //undefined

 

另一种情况是不完全解构,即等号左边的模式只匹配一部分等号右边的数组,这种情况下,解构依然成功

let [x, y] = [1, 2, 3];

x // 1
y // 2

 

[默认值]

解构赋值允许制定默认值。

let [foo = true] = [];
foo // true

 

es6内部使用严格相等运算符(===),判断一个位置是否有值。只有数组成员严格等于undefined,默认值才会生效。

let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
let [x = 'a'] = [null];
x // null

null不严格等于undefined,因此默认值不生效

 

2) 对象的解构赋值

解构不仅可以用于数组,还可以应用于对象。

let { bar, foo } = { foo: "aaa", bar: "bbb" };

foo // "aaa"

bar // "bbb"

 等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。

 

let { baz } = { foo: "aaa", bar: "bbb" };

baz // undefined

变量没有对应的同名属性,导致取不到值,最后等于undefined

 

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

let { foo: baz } = { foo: "aaa", bar: "bbb" };

baz // "aaa"

foo // error: foo is not defined

foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo

 

3)字符串的解构赋值

const [a, b, c, d, e] = 'hello';

a // "h"

b // "e"

c // "l"

d // "l"

e // "o"

 

还可以对字符串的length属性解构赋值

let { length: len } = 'hello';

len // 5

 

4) 数值和布尔值的解构赋值

解构赋值是,登等号右边是数值或布尔值,则会先转为对象。

let { toString: s } = 123;

s === Number.prototype.toString // true


let { toString: s } = true;

s === Boolean.prototype.toString // true

 

5) 函数参数的解构赋值

函数的参数也可使用解构赋值。

function add([x, y]) {

    return x + y;

}

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

 

6) 用途

变量的解构赋值的用途:

·交换变量的值

let x = 1;

let y = 2;

[x, y] = [y, x];

 

·从函数返回多个值

函数只能返回一个值,如果要返回多个值,只能把他们放在数组或对象里返回。有了解构赋值,取出这些值非常方便。

 

// 返回一个数组

function example() {

    return [1, 2, 3];

}

let [a, b, c] = example();

 

// 返回一个对象

function example() {

    return {

        foo: 1,

        bar: 2

    };

}

let { foo, bar } = example();

 

·函数参数的定义

解构赋值可以方便地将一组参数与变量名对应。

 

// 参数是一组有次序的值

function f([x, y, z]) { ... }

f([1, 2, 3]);

 

// 参数是一组无次序的值

function f({ x, y, z }) { ... }

f({ z: 3, y: 2, x: 1 });

 

·提取数据

解构赋值对提取JSON对象中的数据尤其有用。

let jsonData = {

    id: 42,

    status: "OK",

    data: [867, 5309]

};



let { id, status, data: number } = jsonData;

console.log(id, status, number);

// 42, "OK", [867, 5309]

 

·函数参数的默认值

指定参数的默认值,就避免了在函数内部再写var foo = config.foo || ‘default foo’。

jQuery.ajax = function (url, {

    async = true,

    beforeSend = function () {},

    cache = true,

    complete = function () {},

    crossDomain = false,

    global = true,

    // ... more config

}) {

    // ... do stuff

};

 

·遍历Map解构

任何部署iterator接口对象,都可以for.. ig循环遍历。Map结构原生Iterstor接口配合变量法人结构和赋值,获取键名和键值就非常方便。

const map = new Map();

map.set('first', 'hello');

map.set('second', 'world');

 

for (let [key, value] of map) {

    console.log(key + " is " + value);

}

// first is hello

// second is world

 

·输入模块的指定方法

const { SourceMapConsumer, SourceNode } = require("source-map");

 

posted @ 2018-01-23 10:21  zi_chil  阅读(119)  评论(0编辑  收藏  举报