ES6学习笔记(二)
接着上一篇的说。
arrow functions 箭头函数
=> 更便捷的函数声明
document.getElementById("click_1").onclick = function(){ console.log("say Hi!"); } document.getElementById("click_2").onclick = () => { let a = 1; let b = 2; console.log(a + b); }
之前的 function 声明可以被 => 代替,书写起来更便捷。
箭头函数还有个更炫酷也是最使用的用法。
先看个常见的例子:
class people{ constructor(){ this.age = 18; } say(){ setTimeout(function(){ console.log("I'm " + this.age + " year old."); },2000) } } let children = new people(); children.say(); // I'm undefined year old.
这里的this指向内层function对象,所以出现undefined,这就是比较蛋疼的bug。为了方便理解上个截图说明
传统解决方案:
class people{ constructor(){ this.age = 18; } say(){ var self = this; setTimeout(function(){ console.log("I'm " + self.age + " year old."); },2000) } } let children = new people(); children.say(); // I'm 18 year old.
将this在函数内传递给一个变量再使用。或者
class people{ constructor(){ this.age = 18; } say(){ setTimeout(function(){ console.log("I'm " + this.age + " year old."); }.bind(this),2000) } } let children = new people(); children.say(); // I'm 18 year old.
用 bind(this) 指明this的对象
再来看看用 => 的做法
class people{ constructor(){ this.age = 18; } say(){ setTimeout( ()=>{ console.log("I'm " + this.age + " year old."); },2000) } } let children = new people(); children.say(); // I'm 18 year old.
简单省事儿阅读清晰。
template string
这玩儿超好用,一旦用上你会爱不释手,下面来看一段案例:
class people{ constructor(name,age,comeFrom){ this.name = name; this.age = age; this.comeFrom = comeFrom; } } // 实例化对象 let XiaoM = new people("小明",18,"中国"); // 传统写法 console.log("我叫"+XiaoM.name+",今年"+XiaoM.age+"岁,我来自"+XiaoM.comeFrom+"。"); // template string写法 document.write(`我叫<font color="red">${XiaoM.name}</font>,今年<b>${XiaoM.age}</b>岁,我来自${XiaoM.comeFrom}。`); console.log(`我叫${XiaoM.name},今年${XiaoM.age}岁,我来自${XiaoM.comeFrom}。`);
template string有点类似C#中的string.format,不过个人感觉template string比string.format更直观。
用反引号(`
)来标识起始,用
${}来引用变量,而且所有的空格和缩进都会被保留在输出之中,是不是非常爽?!
说明下 反引号在大键盘数字键1的前面一个就是~下面的那个(很惭愧我找反引号找了一会才找到,我开始误以为是单引号)
React Router从第1.0.3版开始也使用ES6语法了,例:
<Link to={`/taco/${taco.name}`}>{taco.name}</Link>
destructuring
更简介易懂的解构。先来看下数组解构
arr_animal = ["cat","dog","mouse"]; // 传统写法 var c = arr_animal[0]; var d = arr_animal[1]; var m = arr_animal[2]; // destructuring解构 var [c,d,m] = arr_animal;
解构也可以跳过数组中的一些元素,如:
arr_animal = ["cat","dog","mouse"]; var [,d,] = arr_animal;
还可以取除开头元素外的剩余元素,如:
arr_num = [1,2,3,4,5,6,7,8,9,0]; var [no1,no2, ...noX] = arr_num; console.log(noX); // [3,4,5,6,7,8,9,0]
注:...noX只能放在最后,否则报错。
看下对象解构
var objA = { name: "A",age: 12 }; var objB = { name: "B",age: 18 }; var { name: nameA,age: ageA } = objA; var { name: nameB,age: ageB } = objB; console.log(nameA,ageA); // A 12 console.log(nameB,ageB); // B 18
通常用以下写法更简明
var { name , age } = { name:"XiaoM", age:18 } console.log(name,age); // XiaoM 18
注:这种写法仅限 解构变量名 与 属性名 相同,否则解构变量为undefined。
看一个嵌套的例子:
var complicatedObj = { arrayProp: [ "Zapp", { second: "Brannigan" } ] }; var { arrayProp: [first, { second }] } = complicatedObj; console.log(first); // "Zapp" console.log(second); // "Brannigan"
注:这里只能解构 first 和 second ,不能解构 arrayProp , 因为这里 相对于被解构的 first 和 second 来说 arrayProp 是一个数组。
若需要解构 arrayProp
var complicatedObj = { arrayProp: [ "Zapp", { second: "Brannigan" } ] }; var { arrayProp } = complicatedObj; console.log(arrayProp); // ["Zapp", Object]
请注意:当解构对象并赋值给变量时,如果你已经声明或不打算声明这些变量(亦即赋值语句前没有let
、const
或var
关键字),你应该注意这样一个潜在的语法错误:
{ blowUp } = { blowUp: 10 }; // Syntax error 语法错误
为什么会出错?这是因为JavaScript语法通知解析引擎将任何以{开始的语句解析为一个块语句(例如,{console}
是一个合法块语句)。解决方案是将整个表达式用一对小括号包裹:
({ safe } = {});
解构值不是对象、数组或迭代器
当尝试解构null
或undefined
时,你会得到一个类型错误:
var {blowUp} = null; // TypeError: null has no properties(null没有属性)
然而,可以解构其它原始类型,例如:布尔值
、数值
、字符串
,但是你将得到undefined
:
var {wtf} = NaN; console.log(wtf); // undefined
这里可能对此感到意外,但经过进一步审查你就会发现,原因其实非常简单。当使用对象赋值模式时,被解构的值需要被强制转换为对象。大多数类型都可以被转换为对象,但null
和undefined
却无法进行转换。当使用数组赋值模式时,被解构的值一定要包含一个迭代器。
当你要解构的属性未定义时你可以提供一个默认值
var [missing = true] = []; console.log(missing); // true var { message: msg = "Something went wrong" } = {}; console.log(msg); // "Something went wrong" var { x = 3 } = {}; console.log(x); // 3
解构的实际应用场景
多重返回值
返回一个数组,然后解构
function returnMultipleValues() { return [1, 2]; } var [foo, bar] = returnMultipleValues();
返回值封装为一个对象并命名属性,然后解构
function returnMultipleValues() { return { foo: 1, bar: 2 }; } var { foo, bar } = returnMultipleValues();
函数参数定义
作为开发者,我们需要实现设计良好的API,通常的做法是为函数为函数设计一个对象作为参数,然后将不同的实际参数作为对象属性,以避免让API使用者记住 多个参数的使用顺序。我们可以使用解构特性来避免这种问题,当我们想要引用它的其中一个属性时,大可不必反复使用这种单一参数对象。
function removeBreakpoint({ url, line, column }) { // ... }
这种函数设计在开发中非常受欢迎。