ES6新语法之---对象字面量扩展模板字符串

Posted 诸葛不亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6新语法之---对象字面量扩展模板字符串相关的知识,希望对你有一定的参考价值。

这节课学习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新语法之---对象字面量扩展模板字符串的主要内容,如果未能解决你的问题,请参考以下文章

ES6对象的新功能与解构赋值

ES6的新特性

ES6的新特性

ES6模板字面量

ES6模板字面量

《深入理解ES6》之扩展对象的功能性