1、let
基本用法
ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。(例如大括号之内,for循环体内)
不存在变量提升
let不像var那样,会发生“变量提升”现象。//局部就是局部,不能变为全局
console.log("ES5:");
var a = [];
for (var i = 0; i < 10; i++) {
var c = i;
a[i] = function () {
console.log(c);
};
};
a[5](); //9
//ES6
console.log("ES6:");
var b = [];
for (var j = 0; j < 10; j++) {
let d = j;
b[j] = function () {
console.log(d);
};
};
b[5](); //5
暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。//作用域内一切都是以let为准
var a = 100;
{
console.log(a); //undefined
let a = 100;
console.log(a); //100
}
不允许重复声明
let不允许在相同作用域内,重复声明同一个变量。
// 模块之间不影响,可以重复声明
{
var a = 100;
var a = 200;
console.log(a);//200
}
{
let a = 300;
console.log(a);//300
}
// 模块内部不允许用let命令重复声明
{
var a = 1;
let a = 2;
console.log(a);//报错
}
2、块级作用域
为什么需要块级作用域?
ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
第一种场景,内层变量可能会覆盖外层变量。
var time = new Date();
function fun() {
console.log(time);
if (false) {
var time = "Hello World!";
};
};
fun(); //undefined,因为fun函数里面有定义time,因此会去找time,但是因为没有进入if判断语句,time就找不到,因此就是undefined,把外层变量覆盖了。可以理解为fun是入口,一进去就要输出time,但是time没有定义。
第二种场景,用来计数的循环变量泄露为全局变量。
var string = "Hello World!";
for (var i = 0; i < string.length; i++) {
console.log(string[i]);
};
console.log("循环结束");
console.log(i); //12,即使跳到外面
ES6的块级作用域
let实际上为JavaScript新增了块级作用域。
<script type="text/javascript">
console.log("ES5:");
function fun() {
var num = 100;
if (true) {
var num = 200;
};
console.log(num);
};
fun(); //200
</script>
<script type="text/traceur">
console.log("ES6:");
function fun() {
let num = 100;
if (true) {
let num = 200;
};
console.log(num);
};
fun(); //100
立即执行函数:
要在函数体后面加括号就能立即调用,则这个函数必须是函数表达式,不能是函数声明。
函数表达式 var fnName = function () {…};使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。
在function前面加!、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式,消除了javascript引擎识别函数表达式和函数声明的歧义,告诉javascript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码。
console.log("ES5:");
function fun() {
console.log("I am outside!");
};
(function () {
if (false) {
function fun() {
console.log("I am inside!");
};
};
fun(); //I am inside! 因为是立即执行函数,里面的fun函数不管是false还是true,都是会提取出来立即执行,覆盖外面的fun函数
}());
</script>
<script type="text/traceur">
console.log("ES6:");
function fun() {
console.log("I am outside!");
};
(function () {
if (false) {
function fun() {
console.log("I am inside!");
};
};
fun(); //I am inside! es6中代码块是独立的,里面的fun函数代码块不会影响到外面,因此输出的是外面的fun函数结果
}());
3、const命令
const也用来声明变量,但是声明的是常量。
一旦声明,常量的值就不能改变。
不可重复声明
块级作用域:
if (true) {
const Pi = 3.14159265;
};
console.log(Pi); //Pi is not defined
暂时性死区:
if (true) {
console.log(Pi); //undefined
const Pi = 3.14159265;
};
const对象:
const person = {};
person.name = "Zhangsan";
person.age = 30;
console.log(person.name);
console.log(person.age);
console.log(person);
person = {}; //person is read-only,可以改变增加对象的属性,但是不能重新赋值
const数组:
const arr = [];
console.log(arr);
console.log(arr.length);
console.log("------");
arr.push("Hello world!");
console.log(arr);
console.log(arr.length);
console.log("------");
arr.length = 0;
console.log(arr);
console.log(arr.length);
console.log("------");
// 错误用法,不能采用重新赋值的方法,要增加元素只能push
arr = ["Hello Everyone!"];
const对象冻结:采用了对象冻结,就不能在后来增加和改变属性,要有属性,只能在赋值的时候设置
const person = Object.freeze({});
person.name = "Zhangsan";
person.age = 30;
console.log(person.name); //undefined
console.log(person.age); //undefined
console.log(person); //Object
const person = Object.freeze({
name: "Zhangsan",
age : 30
});
console.log(person.name); //Zhangsan
console.log(person.age); //30
console.log(person); //Object
跨模块常量:
const声明的常量只在当前代码块有效。
如果想设置跨模块的常量,应该怎么办呢?以下是指在不同的js文件中的写法
// module.js
export const intVariantName = 100;
export const FloatVariantName = 3.14159165;
export const charVariantName = "variantValue";
// use.js
import * as variant from './module';
console.log(variant.intVariantName); //100
console.log(variant.FloatVariantName); //3.14159165
console.log(variant.charVariantName); //variantValue
// otherUse.js
import { FloatVariantName, charVariantName } as variant from './module';
console.log(variant.FloatVariantName); //3.14159165
console.log(variant.charVariantName); //variantValue
// OnlyInt.js
import intVariantName as variant from './module';
console.log(variant.intVariantName); //100
全局对象的属性:
全局对象是最顶层的对象,在浏览器环境指的是window对象,在Node.js指的是global对象。在JavaScript语言中,所有全局变量都是全局对象的属性。(Node的情况比较特殊,这一条只对REPL环境适用,模块环境必须显式声明成global的属性。)
ES6规定,var命令和function命令声明的全局变量,属于全局对象的属性;let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。
var varName = "varValue";
// 浏览器环境下
console.log(window.varName); //varValue
// Node.js环境下
//console.log(global.varName); //varValue
// 通用环境
console.log(this.varName); //varValue
let letName = "letValue";
console.log(window.letName); //undefined -- use strict
console.log(this.letName); //undefined -- use strict
4、数组的结构赋值
Destructuring
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring) 。
let [foo, [[bar], base]] = [1, [[2], 3]];
console.log(foo); //1
console.log(bar); //2
console.log(base); //3
let [, , third] = ["first", "second", "third"];
console.log(third); //third
let [one, , three] = ["One", "Two", "Three"];
console.log(one); //One
console.log(three); //Three
let [head, ...tail] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(head); //0
console.log(tail); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
解构不成功:
var [temp] = [];
console.log(temp); //undefined
var [first, second] = [100];
console.log(first); //100
console.log(second);//undefined
不完全解构
等号左边的模式,只匹配一部分的等号右边的数组。
let [x, y] = [1, 2, 3];
console.log(x); //1
console.log(y); //2
let [a, [b], c] = [1, [2, 3], 4];
console.log(a); //1
console.log(b); //2
console.log(c); //4
指定默认值
注意:ES6内部使用严格相等运算符(===)判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。
var [temp = "string"] = [];
console.log(temp); //string
var [temp = "string"] = ["tempString"];
console.log(temp); //tempString
var [x = "aaa", y] = ["bbb"];
console.log(x); //bbb
console.log(y); //undefined
var [m, n = "aaa"] = ["bbb"];
console.log(m); //bbb
console.log(n); //aaa
var [p, q = "aaa"] = ["bbb", undefined];
console.log(p); //bbb
console.log(q); //aaa
非遍历解构--报错
var [temp] = 1; //1[Symbol.iterator] is not a function at eval
var [temp] = false; //false[Symbol.iterator] is not a function at eval
var [temp] = NaN; //NaN[Symbol.iterator] is not a function at eval
var [temp] = undefined; //Cannot read property 'Symbol(Symbol.iterator)' of undefined at eval
var [temp] = null; //Cannot read property 'Symbol(Symbol.iterator)' of null at eval
let和const命令
只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。
let [a, b, c] = new Set(["a", "b", "c"]);
console.log(a); //a
console.log(b); //b
console.log(c); //c
function* fibs() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
};
var [first, second, third, fourth, fifth, sixth] = fibs();
console.log(sixth); //5
5、对象的解构赋值
解构不仅可以用于数组,还可以用于对象
对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
var { name, age } = { name: "Conan", age: 28 };
console.log(name); //Conan
console.log(age); //28
解构赋值不用按照顺序:
var { name, age, id } = { id: "007", name: "Conan", age: 28 };
console.log(name); //Conan
console.log(age); //28
console.log(id); //007
变量名和属性名不一致时:
var { name: person_name, age: person_age, id: person_id } = { id: "007", name: "Conan", age: 28 };
console.log(person_name); //Conan
console.log(person_age); //28
console.log(person_id); //007
let object = { first: "Hello", last: "World" };
let { first: firstName, last: lastName} = object;
console.log(firstName); //Hello
console.log(lastName); //World
指定默认值
默认值生效的条件是,对象的属性值严格等于undefined。
对象解构默认值:
var { x = 3 } = {};
console.log(x); //3
var { x, y = 5 } = { x: 1 };
console.log(x); //1
console.log(y); //5
var { message: msg = "You Are A Person!" } = {};
console.log(msg); //You Are A Person!
对象解构默认值条件:undefined
var { x = 3 } = { x: undefined };
console.log(x); //3
var { y = 3 } = { y: null };
console.log(y); //null
已声明变量的解构赋值,要带有小括号
var x;
({x} = { x: 1 });
console.log(x); //1
现有对象的方法
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量
console.log(Math.sin(Math.PI/6)); //0.49999999999999994
let { sin, cos, tan, log } = Math;
console.log(sin(Math.PI/6)); //0.49999999999999994
上面代码将Math对象的正弦、余弦、正切、对数三个方法,赋值到对应的变量上,使用起来就会方便很多。
6、字符串的解构赋值
字符串也可以解构赋值
字符串被转换成了一个类似数组的对象。
const [ a, b, c, d, e ] = "Hello";
console.log(a); //H
console.log(b); //e
console.log(c); //l
console.log(d); //l
console.log(e); //o
属性解构赋值
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
const { length: len } = "Hello";
console.log(len); //5
const { length } = "Hello World!";
console.log(length);//12
7、函数参数的解构赋值
函数的参数也可以使用解构。
function sum([x, y]) {
return x + y;
};
console.log(sum([1, 2])); //3
函数参数的解构也可以使用默认值。
function fun ({x = 0, y = 0} = {}) {
return [x, y];
};
console.log(fun({x: 100, y: 200})); //[100, 200]
console.log(fun({x: 100})); //[100, 0]
console.log(fun({})); //[0, 0]
console.log(fun()); //[0, 0]
function fun ({x, y} = { x: 0, y: 0 }) {
return [x, y];
};
//想要默认值有效,必需设置在前面
console.log(fun({x: 100, y: 200})); //[100, 200]
console.log(fun({x: 100})); //[100, undefined]
console.log(fun({})); //[undefined, undefined]
console.log(fun()); //[0, 0]
8、解构赋值的用途
1)交换变量的值
//ES5
console.log("ES5:");
var a = 100;
var b = 200;
console.log("交换前:");
console.log("a = " + a); //a = 100
console.log("b = " + b); //b = 200
var temp;
temp = a;
a = b;
b = temp;
console.log("交换后:");
console.log("a = " + a); //a = 200
console.log("b = " + b); //b = 100
//ES6
console.log("ES6:");
var x = 100;
var y = 200;
console.log("交换前:");
console.log("x = " + x); //x = 100
console.log("y = " + y); //y = 200
[x, y] = [y, x];
console.log("交换后:");
console.log("x = " + x); //x = 200
console.log("y = " + y); //y = 100
2)从函数返回多个值
数组:
function fun () {
return [1, 2, 3];
};
var [x, y, z] = fun();
console.log(x); //1
console.log(y); //2
console.log(z); //3
对象:
function fun () {
return {
id : "007",
name: "Conan",
age : 28
};
};
var { id, name, age } = fun();
console.log(id); //007
console.log(name); //Conan
console.log(age); //28
var { id: person_id, name: person_name, age: person_age } = fun();
console.log(person_id); //007
console.log(person_name); //Conan
console.log(person_age); //28
3)函数参数的定义
// 参数是一组有次序的值
function fun ([x, y, z]) {
//x = 100;
//y = 200;
//z = 300;
};
fun([100, 200, 300]);
// 参数是一组无次序的值
function fun ({id, name, age}) {
//id = "007";
//name = "Conan";
//age = 28;
};
fun({id: "007", name: "Conan", age: 28});
4)提取json数据用法
var jsonData={
name: "Conan",
age: 28,
score: {
Chinese: 98,
Math: 148,
English: 107
}
};
console.log(jsonData);
console.log("ES5:");
console.log("Person's Number is:" + jsonData.id);
console.log("Person's Name is:" + jsonData.name);
console.log("Person's age is:" + jsonData.age);
console.log("Person's Chinese score is:" + jsonData.score.Chinese);
console.log("Person's Math score is:" + jsonData.score.Math);
console.log("Person's English score is:" + jsonData.score.English);
console.log("ES6:");
let { id: number, name, age, score: score } = jsonData;
console.log("Person's Number is:" + number);
console.log("Person's Name is:" + name);
console.log("Person's age is:" + age);
console.log("Person's Chinese score is:" + score.Chinese);
console.log("Person's Math score is:" + score.Math);
console.log("Person's English score is:" + score.English);
5) 函数参数的默认值
jQuery.ajax({
url: '/path/to/file',
type: 'POST',
dataType: 'xml/html/script/json/jsonp',
data: {param1: 'value1'},
complete: function(xhr, textStatus) {
//called when complete
},
success: function(data, textStatus, xhr) {
//called when successful
},
error: function(xhr, textStatus, errorThrown) {
//called when there is an error
}
});
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'; 这样的语句
function(config){
var foo = config.foo || 'default foo'
return foo
}
其实意思就是,想给foo指定一个值得话,我们就判断参数中的config对象中有没有foo属性,如果有直接赋值给var foo这个变量,否则走后半部分,foo = 'default foo'让foo等于default foo这个字符串
这样写的好处就是,就算调用这个方法不传参数,也能保证foo变量有值,也就是所谓的默认值
但是有了ES6就不用这么麻烦了,直接在参数中就可以赋默认值了,以下是阮一峰老师的标准ES6中是实例
函数参数的解构也可以使用默认值
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]
6)遍历map结构
var map = new Map();
map.set("id", "007");
map.set("name", "Conan");
console.log(map);
console.log(typeof(map));
// 获取键名和键值
for (let [key, value] of map) {
console.log(key + " is " + value);
};
// id is 007
// name is Conan
// 获取键名
for (let [key] of map) {
console.log(key);
};
// id
// name
for (let [, value] of map) {
console.log(value);
};
// 007
// Conan
7)输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");
基本用法
ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。(例如大括号之内,for循环体内)
不存在变量提升
let不像var那样,会发生“变量提升”现象。//局部就是局部,不能变为全局
console.log("ES5:");
var a = [];
for (var i = 0; i < 10; i++) {
var c = i;
a[i] = function () {
console.log(c);
};
};
a[5](); //9
//ES6
console.log("ES6:");
var b = [];
for (var j = 0; j < 10; j++) {
let d = j;
b[j] = function () {
console.log(d);
};
};
b[5](); //5
暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。//作用域内一切都是以let为准
var a = 100;
{
console.log(a); //undefined
let a = 100;
console.log(a); //100
}
不允许重复声明
let不允许在相同作用域内,重复声明同一个变量。
// 模块之间不影响,可以重复声明
{
var a = 100;
var a = 200;
console.log(a);//200
}
{
let a = 300;
console.log(a);//300
}
// 模块内部不允许用let命令重复声明
{
var a = 1;
let a = 2;
console.log(a);//报错
}
2、块级作用域
为什么需要块级作用域?
ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
第一种场景,内层变量可能会覆盖外层变量。
var time = new Date();
function fun() {
console.log(time);
if (false) {
var time = "Hello World!";
};
};
fun(); //undefined,因为fun函数里面有定义time,因此会去找time,但是因为没有进入if判断语句,time就找不到,因此就是undefined,把外层变量覆盖了。可以理解为fun是入口,一进去就要输出time,但是time没有定义。
第二种场景,用来计数的循环变量泄露为全局变量。
var string = "Hello World!";
for (var i = 0; i < string.length; i++) {
console.log(string[i]);
};
console.log("循环结束");
console.log(i); //12,即使跳到外面
ES6的块级作用域
let实际上为JavaScript新增了块级作用域。
<script type="text/javascript">
console.log("ES5:");
function fun() {
var num = 100;
if (true) {
var num = 200;
};
console.log(num);
};
fun(); //200
</script>
<script type="text/traceur">
console.log("ES6:");
function fun() {
let num = 100;
if (true) {
let num = 200;
};
console.log(num);
};
fun(); //100
立即执行函数:
要在函数体后面加括号就能立即调用,则这个函数必须是函数表达式,不能是函数声明。
函数表达式 var fnName = function () {…};使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。
在function前面加!、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式,消除了javascript引擎识别函数表达式和函数声明的歧义,告诉javascript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码。
console.log("ES5:");
function fun() {
console.log("I am outside!");
};
(function () {
if (false) {
function fun() {
console.log("I am inside!");
};
};
fun(); //I am inside! 因为是立即执行函数,里面的fun函数不管是false还是true,都是会提取出来立即执行,覆盖外面的fun函数
}());
</script>
<script type="text/traceur">
console.log("ES6:");
function fun() {
console.log("I am outside!");
};
(function () {
if (false) {
function fun() {
console.log("I am inside!");
};
};
fun(); //I am inside! es6中代码块是独立的,里面的fun函数代码块不会影响到外面,因此输出的是外面的fun函数结果
}());
3、const命令
const也用来声明变量,但是声明的是常量。
一旦声明,常量的值就不能改变。
不可重复声明
块级作用域:
if (true) {
const Pi = 3.14159265;
};
console.log(Pi); //Pi is not defined
暂时性死区:
if (true) {
console.log(Pi); //undefined
const Pi = 3.14159265;
};
const对象:
const person = {};
person.name = "Zhangsan";
person.age = 30;
console.log(person.name);
console.log(person.age);
console.log(person);
person = {}; //person is read-only,可以改变增加对象的属性,但是不能重新赋值
const数组:
const arr = [];
console.log(arr);
console.log(arr.length);
console.log("------");
arr.push("Hello world!");
console.log(arr);
console.log(arr.length);
console.log("------");
arr.length = 0;
console.log(arr);
console.log(arr.length);
console.log("------");
// 错误用法,不能采用重新赋值的方法,要增加元素只能push
arr = ["Hello Everyone!"];
const对象冻结:采用了对象冻结,就不能在后来增加和改变属性,要有属性,只能在赋值的时候设置
const person = Object.freeze({});
person.name = "Zhangsan";
person.age = 30;
console.log(person.name); //undefined
console.log(person.age); //undefined
console.log(person); //Object
const person = Object.freeze({
name: "Zhangsan",
age : 30
});
console.log(person.name); //Zhangsan
console.log(person.age); //30
console.log(person); //Object
跨模块常量:
const声明的常量只在当前代码块有效。
如果想设置跨模块的常量,应该怎么办呢?以下是指在不同的js文件中的写法
// module.js
export const intVariantName = 100;
export const FloatVariantName = 3.14159165;
export const charVariantName = "variantValue";
// use.js
import * as variant from './module';
console.log(variant.intVariantName); //100
console.log(variant.FloatVariantName); //3.14159165
console.log(variant.charVariantName); //variantValue
// otherUse.js
import { FloatVariantName, charVariantName } as variant from './module';
console.log(variant.FloatVariantName); //3.14159165
console.log(variant.charVariantName); //variantValue
// OnlyInt.js
import intVariantName as variant from './module';
console.log(variant.intVariantName); //100
全局对象的属性:
全局对象是最顶层的对象,在浏览器环境指的是window对象,在Node.js指的是global对象。在JavaScript语言中,所有全局变量都是全局对象的属性。(Node的情况比较特殊,这一条只对REPL环境适用,模块环境必须显式声明成global的属性。)
ES6规定,var命令和function命令声明的全局变量,属于全局对象的属性;let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。
var varName = "varValue";
// 浏览器环境下
console.log(window.varName); //varValue
// Node.js环境下
//console.log(global.varName); //varValue
// 通用环境
console.log(this.varName); //varValue
let letName = "letValue";
console.log(window.letName); //undefined -- use strict
console.log(this.letName); //undefined -- use strict
4、数组的结构赋值
Destructuring
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring) 。
let [foo, [[bar], base]] = [1, [[2], 3]];
console.log(foo); //1
console.log(bar); //2
console.log(base); //3
let [, , third] = ["first", "second", "third"];
console.log(third); //third
let [one, , three] = ["One", "Two", "Three"];
console.log(one); //One
console.log(three); //Three
let [head, ...tail] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(head); //0
console.log(tail); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
解构不成功:
var [temp] = [];
console.log(temp); //undefined
var [first, second] = [100];
console.log(first); //100
console.log(second);//undefined
不完全解构
等号左边的模式,只匹配一部分的等号右边的数组。
let [x, y] = [1, 2, 3];
console.log(x); //1
console.log(y); //2
let [a, [b], c] = [1, [2, 3], 4];
console.log(a); //1
console.log(b); //2
console.log(c); //4
指定默认值
注意:ES6内部使用严格相等运算符(===)判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。
var [temp = "string"] = [];
console.log(temp); //string
var [temp = "string"] = ["tempString"];
console.log(temp); //tempString
var [x = "aaa", y] = ["bbb"];
console.log(x); //bbb
console.log(y); //undefined
var [m, n = "aaa"] = ["bbb"];
console.log(m); //bbb
console.log(n); //aaa
var [p, q = "aaa"] = ["bbb", undefined];
console.log(p); //bbb
console.log(q); //aaa
非遍历解构--报错
var [temp] = 1; //1[Symbol.iterator] is not a function at eval
var [temp] = false; //false[Symbol.iterator] is not a function at eval
var [temp] = NaN; //NaN[Symbol.iterator] is not a function at eval
var [temp] = undefined; //Cannot read property 'Symbol(Symbol.iterator)' of undefined at eval
var [temp] = null; //Cannot read property 'Symbol(Symbol.iterator)' of null at eval
let和const命令
只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。
let [a, b, c] = new Set(["a", "b", "c"]);
console.log(a); //a
console.log(b); //b
console.log(c); //c
function* fibs() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
};
var [first, second, third, fourth, fifth, sixth] = fibs();
console.log(sixth); //5
5、对象的解构赋值
解构不仅可以用于数组,还可以用于对象
对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
var { name, age } = { name: "Conan", age: 28 };
console.log(name); //Conan
console.log(age); //28
解构赋值不用按照顺序:
var { name, age, id } = { id: "007", name: "Conan", age: 28 };
console.log(name); //Conan
console.log(age); //28
console.log(id); //007
变量名和属性名不一致时:
var { name: person_name, age: person_age, id: person_id } = { id: "007", name: "Conan", age: 28 };
console.log(person_name); //Conan
console.log(person_age); //28
console.log(person_id); //007
let object = { first: "Hello", last: "World" };
let { first: firstName, last: lastName} = object;
console.log(firstName); //Hello
console.log(lastName); //World
指定默认值
默认值生效的条件是,对象的属性值严格等于undefined。
对象解构默认值:
var { x = 3 } = {};
console.log(x); //3
var { x, y = 5 } = { x: 1 };
console.log(x); //1
console.log(y); //5
var { message: msg = "You Are A Person!" } = {};
console.log(msg); //You Are A Person!
对象解构默认值条件:undefined
var { x = 3 } = { x: undefined };
console.log(x); //3
var { y = 3 } = { y: null };
console.log(y); //null
已声明变量的解构赋值,要带有小括号
var x;
({x} = { x: 1 });
console.log(x); //1
现有对象的方法
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量
console.log(Math.sin(Math.PI/6)); //0.49999999999999994
let { sin, cos, tan, log } = Math;
console.log(sin(Math.PI/6)); //0.49999999999999994
上面代码将Math对象的正弦、余弦、正切、对数三个方法,赋值到对应的变量上,使用起来就会方便很多。
6、字符串的解构赋值
字符串也可以解构赋值
字符串被转换成了一个类似数组的对象。
const [ a, b, c, d, e ] = "Hello";
console.log(a); //H
console.log(b); //e
console.log(c); //l
console.log(d); //l
console.log(e); //o
属性解构赋值
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
const { length: len } = "Hello";
console.log(len); //5
const { length } = "Hello World!";
console.log(length);//12
7、函数参数的解构赋值
函数的参数也可以使用解构。
function sum([x, y]) {
return x + y;
};
console.log(sum([1, 2])); //3
函数参数的解构也可以使用默认值。
function fun ({x = 0, y = 0} = {}) {
return [x, y];
};
console.log(fun({x: 100, y: 200})); //[100, 200]
console.log(fun({x: 100})); //[100, 0]
console.log(fun({})); //[0, 0]
console.log(fun()); //[0, 0]
function fun ({x, y} = { x: 0, y: 0 }) {
return [x, y];
};
//想要默认值有效,必需设置在前面
console.log(fun({x: 100, y: 200})); //[100, 200]
console.log(fun({x: 100})); //[100, undefined]
console.log(fun({})); //[undefined, undefined]
console.log(fun()); //[0, 0]
8、解构赋值的用途
1)交换变量的值
//ES5
console.log("ES5:");
var a = 100;
var b = 200;
console.log("交换前:");
console.log("a = " + a); //a = 100
console.log("b = " + b); //b = 200
var temp;
temp = a;
a = b;
b = temp;
console.log("交换后:");
console.log("a = " + a); //a = 200
console.log("b = " + b); //b = 100
//ES6
console.log("ES6:");
var x = 100;
var y = 200;
console.log("交换前:");
console.log("x = " + x); //x = 100
console.log("y = " + y); //y = 200
[x, y] = [y, x];
console.log("交换后:");
console.log("x = " + x); //x = 200
console.log("y = " + y); //y = 100
2)从函数返回多个值
数组:
function fun () {
return [1, 2, 3];
};
var [x, y, z] = fun();
console.log(x); //1
console.log(y); //2
console.log(z); //3
对象:
function fun () {
return {
id : "007",
name: "Conan",
age : 28
};
};
var { id, name, age } = fun();
console.log(id); //007
console.log(name); //Conan
console.log(age); //28
var { id: person_id, name: person_name, age: person_age } = fun();
console.log(person_id); //007
console.log(person_name); //Conan
console.log(person_age); //28
3)函数参数的定义
// 参数是一组有次序的值
function fun ([x, y, z]) {
//x = 100;
//y = 200;
//z = 300;
};
fun([100, 200, 300]);
// 参数是一组无次序的值
function fun ({id, name, age}) {
//id = "007";
//name = "Conan";
//age = 28;
};
fun({id: "007", name: "Conan", age: 28});
4)提取json数据用法
var jsonData={
name: "Conan",
age: 28,
score: {
Chinese: 98,
Math: 148,
English: 107
}
};
console.log(jsonData);
console.log("ES5:");
console.log("Person's Number is:" + jsonData.id);
console.log("Person's Name is:" + jsonData.name);
console.log("Person's age is:" + jsonData.age);
console.log("Person's Chinese score is:" + jsonData.score.Chinese);
console.log("Person's Math score is:" + jsonData.score.Math);
console.log("Person's English score is:" + jsonData.score.English);
console.log("ES6:");
let { id: number, name, age, score: score } = jsonData;
console.log("Person's Number is:" + number);
console.log("Person's Name is:" + name);
console.log("Person's age is:" + age);
console.log("Person's Chinese score is:" + score.Chinese);
console.log("Person's Math score is:" + score.Math);
console.log("Person's English score is:" + score.English);
5) 函数参数的默认值
jQuery.ajax({
url: '/path/to/file',
type: 'POST',
dataType: 'xml/html/script/json/jsonp',
data: {param1: 'value1'},
complete: function(xhr, textStatus) {
//called when complete
},
success: function(data, textStatus, xhr) {
//called when successful
},
error: function(xhr, textStatus, errorThrown) {
//called when there is an error
}
});
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'; 这样的语句
function(config){
var foo = config.foo || 'default foo'
return foo
}
其实意思就是,想给foo指定一个值得话,我们就判断参数中的config对象中有没有foo属性,如果有直接赋值给var foo这个变量,否则走后半部分,foo = 'default foo'让foo等于default foo这个字符串
这样写的好处就是,就算调用这个方法不传参数,也能保证foo变量有值,也就是所谓的默认值
但是有了ES6就不用这么麻烦了,直接在参数中就可以赋默认值了,以下是阮一峰老师的标准ES6中是实例
函数参数的解构也可以使用默认值
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]
6)遍历map结构
var map = new Map();
map.set("id", "007");
map.set("name", "Conan");
console.log(map);
console.log(typeof(map));
// 获取键名和键值
for (let [key, value] of map) {
console.log(key + " is " + value);
};
// id is 007
// name is Conan
// 获取键名
for (let [key] of map) {
console.log(key);
};
// id
// name
for (let [, value] of map) {
console.log(value);
};
// 007
// Conan
7)输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");