您的位置:首页 > Web前端 > JavaScript

ECMAScript 6 入门笔记(一)let,const,解构

2017-03-27 13:04 387 查看
ECMAScript 6 入门原文 – 阮一峰

ECMAScript 6 入门笔记(一)let,const,解构

ECMAScript 6 入门笔记(二)String,RegExp

ECMAScript 6 入门笔记(三)数值,Array

ECMAScript 6 入门笔记(四)函数,对象

ECMAScript 6 入门笔记(五)异步promise,Generator,async

ECMAScript 6 入门笔记(六)Class

ECMAScript 6 入门笔记(七)Symbol,set和map

ECMAScript 6 入门笔记(八)Proxy,Reflect

最近重新看下阮一峰的ecmascript6教程,记性不太好,用的也不多所以记下笔记把自己认为重要的东西记录下来方便回顾,贴代码和调整下结构让查起来更快ECMAscript6 入门

LET和CONST

ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。const声明一个只读的常量。一旦声明,常量的值就不能改变,const必须声明时就初始化。let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性,无法用window.访问了

{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1

for (let i = 0; i < 10; i++) {}
console.log(i);
//ReferenceError: i is not defined

var arr = [];
for (let i = 0; i < 10; i++) {   //var 全部会变成10
a[i] = function () {
console.log(i);
};
}
arr[6](); // 6

const PI = 3.1415;
PI = 3;
// TypeError: Assignment to constant variable.
window.PI // undefined 顶层对象脱钩

const foo;
// SyntaxError: Missing initializer in const declaration


let,const不会变量提升

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;


暂时性死区

if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError

let tmp; // TDZ结束
console.log(tmp); // undefined

tmp = 123;
console.log(tmp); // 123
}

function bar(x = y, y = 2) {
return [x, y];
}

bar(); // 报错

if (true) {
console.log(MAX); // ReferenceError
const MAX = 5;
}


不许重复声明

// 报错
function () {
let a = 10;
let a = 1;
}

function func(arg) {
let arg; // 报错
}

function func(arg) {
{
let arg; // 不报错
}
}


ES6块级作用域

function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}

if (true) {
const MAX = 5;
}
MAX // Uncaught ReferenceError: MAX is not defined


块级作用域与函数声明

// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
//默认定义了下var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}

f();
}());
// Uncaught TypeError: f is not a function


const内存指向的地址不能改动,但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。

const foo = {};

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

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

const a = [];
a.push('Hello'); // 可执行
a.length = 0;    // 可执行
a = ['Dave'];    // 报错


变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

数组的解构赋值

let [a, b, c] = [1, 2, 3];
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1    bar // 2      baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []


设置默认值

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

let [i = 1] = [undefined];
i // 1

let [j = 1] = [null];
j // null


对象解构

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

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;

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

let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined

//上面代码中,let命令下面一行的圆括号是必须的,否则会报错。因为解析器会将起首的大括号,理解成一个代码块,而不是赋值语句。

let foo;
({foo} = {foo: 1}); // 成功

let baz;
({bar: baz} = {bar: 1}); // 成功

let obj = {
p: [
'Hello',
{ y: 'World' }
]
};

let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3


函数参数的解构赋值

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

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

function move({x = 0, y = 0} = {}) {
return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]


解构用途

(1)交换变量的值

let x = 1;
let y = 2;

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


(2)从函数返回多个值

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

function example() {
return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象

function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();


(3)函数参数的定义

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

// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});


(4)提取JSON数据

解构赋值对提取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]


(5)函数参数的默认值

jQuery.ajax = function (url, {
async = true,
beforeSend = function () {},
cache = true,
complete = function () {},
crossDomain = false,
global = true,
// ... more config
}) {
// ... do stuff
};


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

(6)遍历Map结构

任何部署了Iterator接口的对象,都可以用for…of循环遍历。Map结构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便。

var 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
如果只想获取键名,或者只想获取键值,可以写成下面这样。

// 获取键名
for (let [key] of map) {
// ...
}

// 获取键值
for (let [,value] of map) {
// ...
}


(7)输入模块的指定方法

加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。

const { SourceMapConsumer, SourceNode } = require("source-map");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ecmascript6 js