1. 程式人生 > >ES6新語法之---對象字面量擴展、模板字符串(5)

ES6新語法之---對象字面量擴展、模板字符串(5)

ons 可靠的 小數 為我 寫法 define 當前 BE dde

這節課學習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)