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还是false,test变量都会被声明。
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) }) }
变量i
是let
声明的,当前的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");