ES6新語法之---對象字面量擴展、模板字符串(5)
這節課學習ES6中對象字面量擴展和新增模板字符串
第一部分:對象字面量擴展
1.簡潔寫法
ES6對於對象字面量屬性提供了簡寫方式。
1.1:屬性簡寫
//傳統寫法 var x = 2, y = 3, o = { x: x, y: y }; //ES6簡潔寫法 var x = 2, y = 3, o = { x, //屬性名和賦值變量名相同時,可簡寫 y };
1.2:方法簡寫
//傳統寫法 var o = { x: function() { //... }, y: function() { //... } } //ES6簡潔寫法 var o = { x() { //... }, y() {//... } }
1.3簡潔方法的局限
分析下面代碼是否可以通過簡潔方法重構:
function runSomething(o) { var x = Math.random(), y = Math.random(); return o.something(x, y); //通過o調用屬性方法 } runSomething({ something: function something(x, y) {if (x > y) { return something(y, x) // 當不符合條件時,遞歸調用something()方法 } return y - x; } });
這裏的‘something:‘屬性和function something()各有用途,屬性something可以通過o對象調用,而function something()在自身內部調用用於遞歸實現。
分析1:在obj對象內部通過obj.something()實現遞歸。
function runSomething(o) { var x = Math.random(), y = Math.random(); return o.something(x, y); //通過o調用屬性方法 } var obj = { something: function(x, y) { if (x > y) { return obj.something(y, x) // 這裏我們使用obj調用functiong } return y - x; } }; runSomething(obj);
如果obj對象的引用指向不發生改變的話,那麽這是一個很好的辦法。但obj的指向我們並不能控制。
分析2:使用this調用obj中的something()方法
var obj = { something: function(x, y) { if (x > y) { return this.something(y, x) // 這裏使用this調用 } return y - x; } };
這裏的this和分析1中的問題一樣,我們無法保證something()方法始終是obj調用的,這樣就會存在this的綁定陷阱,可能this表示的並不是obj本身。
例如:btn.addEventListener("click", obj.something, false);此時的this就不再是obj對象本身了,可能有人說可以使用obj.something.bind(obj)再綁定回去,這麽麻煩就沒必要了。
再回頭看我們最初1.3中的問題:
runSomething({ something: function something(x, y) { if (x > y) { return something(y, x) } return y -x; } })
這裏面function something()中的something總是指向這個something()這個函數本身,為我們提供了一個用於遞歸/事件綁定/解綁的引用,不會和this糾纏也不需要不可靠的對象引用。
使用ES6的語法簡化:
runSomething({ something(x, y) { if (x > y) { return something(y, x) // Uncaught ReferenceError: something is not defined } return y -x; } })
可以看到代碼報錯,因為其中something(x, y)會被解釋為:something:function(x, y){...},這樣return中的something方法就是未定義的。
總結:簡潔方法很方便,但是應該只在不需要他們執行遞歸/事件綁定/解綁時候使用。否則我們還是應該使用 something: function something(){...}這種傳統的方式。
1.4計算屬性名
計算屬性名:對象中一個或多個屬性名是通過某個表達式計算得來的。
var prefix = "user_"; var o = { baz: function () { //... } }; o[prefix + ‘foo‘] = function () { //[]中可以放任意合法表達式 // ... } o[prefix + ‘bar‘] = function () { // ... }
計算屬性名也可以作為簡潔方法的名稱出現:
var o = { ["f" + "oo"]() { // 作為簡潔方法的名稱出現 //... } }
第二部分:模板字符串
1.ES6引入了一個新的字符串字面量,使用`作為界定符,這樣的字符串字面值支持嵌入基本的字符串插入表達式,會被自動解析和求值。
1.1傳統拼接字符串方式:
var name = "Kyle"; var greeting = "Hello " + name + "!"; //使用傳統的‘+‘拼接字符串 console.log(greeting); console.log(typeof greeting);
1.2ES6模板字符串拼接:
var name = "Kyle"; var greeting = `Hello${name}!`; //使用模板字符串,${}可以對變量取值。 console.log(greeting); console.log(typeof greeting);
字符使用``包裹,會被解釋為一個字符串字面量,其中${}形式的表達式會被立即在線解析求值。
1.3字符串字面量的一個優點,字符串可以分散在多行:
// text中的空格和換行會被保存 var text = ` Now is the time for all good men to come to the aid of their country! `; console.log(text);
2.插入表達式${}
2.1插入表達式中可以出現任何合法的表達式,包括函數調用、在線函數表達式調用,甚至其他插入字符串字面量!
function upper(s) { return s.toUpperCase(); } var who = "reader"; var text = ` A very ${upper("warm")} welcome to all of you ${upper(`${who}s`)} `; console.log(text);
2.2插入表達式作用域
function foo(str){ var name = "foo"; console.log(str); } function bar(){ var name = "bar"; foo(`Hello from ${name}!`); //這裏的name使用的是${name}所出現的作用域中的name } var name = "global"; bar(); // Hello from bar
插入字符串字面量在它出現的詞法作用域內,沒有任何形式的動態作用域。
2.3標簽模板字面量
這個新功能不好解釋,直接上代碼比較直觀:
function foo(strings, ...values){ console.log(strings); //輸出結果是數組,[‘Everything is‘, ‘!‘] console.log(values); //輸出結果是數組,[‘awesome‘] } var desc = ‘awesome‘; foo `Everything is ${desc}!`;
上例中foo`Everything...`是什麽?其實這是一類不需要(...)的特殊函數調用,標簽也就是foo部分是一個要調用的函數值。可以是任意結果為函數的表達式。
function bar() { return function foo(strings, ...values){ console.log(strings); //[‘Everything is‘, ‘!‘] console.log(values); // [‘awesome‘] } } var desc = "awesome"; bar()`Everything is ${desc}`; //bar()的結果是一個函數
分析:第一個參數strings為所有由普通字符串組成的數組。
第二個參數values接收的是由插入表達式${}計算的結果值。
應用:數字格式化為美元表示法
function bar(strings, ...values) { return strings.reduce(function(s, v, idx){ //s表示上一次調用返回值,v表示當前元素之 if(idx > 0){ if(typeof values[idx - 1] == ‘number‘){ s += `$${values[idx - 1].toFixed(2)}`; //如果是數字,給其拼接上‘$‘符號。 } else { s += values[idx - 1] } } return s + v; }, ""); //""作為reduce第一次調用的第一個參數的值 } var amt1 = 11.99; amt2 = amt1 * 1.08, name = "Kyle"; var result = bar` Thanks for your purchase, ${amt1}! Your product cost was ${amt1}, which with tax comes out to ${amt2}. `; console.log(result)
如果values中遇到number值,就在其前拼接‘$‘,然後使用toFixed(2)保留兩位小數位。
2.4原始字符串
ES6提供了一個內建函數可以用作字符串字面量標簽:String.raw(...)。得到字符串原始值。
//結果我為‘Hello //World‘ console.log(‘Hello\nWorld!‘); console.log(String.raw`Hello\nWorld!`); //結果為‘Hello\nWorld‘
ES6新語法之---對象字面量擴展、模板字符串(5)