• ES6入门四:对象字面量扩展与字符串模板字面量


    • 简洁属性与简洁方法
    • 计算属性名与[[prototype]]
    • super对象(暂时保留解析)
    • 模板字面量(模板字符串)

     一、简洁属性与简洁方法

    ES6中为了不断优化代码,减低代码的耦合度在语法上下了很大的功夫,上一篇博客解构就是其中一种,在对象属性和方法名称上也有所优化,也就是这篇博客要解析的简洁属性和简洁方法。

    什么是简洁属性呢?当通过字面量的方式声明对象时,属性名与赋值的变量名一致时,就可以采用简洁属性,示例:

     1 //ES6的对象字面量简洁属性
     2 var x = 2, y = 3,
     3     obj = {
     4         x,
     5         y
     6     };
     7 //ES5的编译结果
     8 var x = 2,
     9     y = 3,
    10     obj = {
    11           x: x,
    12           y: y
    13     };

    什么是简洁方法呢?当采用对象字面量的方式声明对象,可以省略方法的function字符,示例:

     1 //ES6的对象字面量简洁方法
     2 var obj = {
     3     foo(){
     4         //...
     5     },
     6     fun(){
     7         //...
     8     }
     9 }
    10 //ES5的编译结果
    11 var obj = {
    12   foo: function foo() {//...
    13   },
    14   fun: function fun() {//...
    15   }
    16 };

    但是简洁方法需要注意,如果在对象方法中出现需要实现递归算法的话,就不能使用简洁方法的语法,比如下面这个代码(ES5的代码)就不能转换成简洁方法的写法:

     1 function ruSomething(o){
     2     var x = Math.random(),
     3         y = Math.random();
     4     return o.something(x, y);
     5 }
     6 
     7 ruSomething({
     8     something:function something( x , y){
     9         if(x > y){
    10         return something(y , x); //这里递归了,请勿使用简洁语法
    11         }
    12         return y - x;
    13     }
    14 });

    为什么不能呢?接着来看简洁语法的写法:

     1 //ES6简洁语法编写上一个示例代码(错误代码,请勿使用)
     2 ruSomething({
     3     something( x , y){
     4         if(x > y){
     5         return something(y , x);
     6         }
     7         return y - x;
     8     }
     9 });
    10 //ES5的编译结果
    11 ruSomething({
    12   something: function (_something) {
    13     function something(_x, _x2) {
    14       return _something.apply(this, arguments);
    15     }
    16 
    17     something.toString = function () {
    18       return _something.toString();
    19     };
    20 
    21     return something;
    22   }(function (x, y) {
    23     if (x > y) {
    24       return something(y, x);
    25     }
    26 
    27     return y - x;
    28   })
    29 });

    因为something(y,x)递归是找不到这个方法的引用,在编译的时候就会认为简洁写法小括号前面是方法执行,后面是一个作用域块,编译时会认为有一个function something(x,y){...}在作用域上,最后导出的ES5的编译结果就是这个奇怪的代码了。

    这时候可能会有人认为给something(y,x)递归加上一个this指向,就可以解决了,来看看这种猜想是否成立:

     1 //ES6中对象方法递归使用this实现
     2 ruSomething({
     3     something( x , y){
     4         if(x > y){
     5         return this.something(y , x);
     6         }
     7         return y - x;
     8     }
     9 });
    10 //ES5的编译结果
    11 ruSomething({
    12   something: function something(x, y) {
    13     if (x > y) {
    14       return this.something(y, x);
    15     }
    16 
    17     return y - x;
    18   }
    19 });

    看着上面的代码好像编译正确了,没有什么问题,但是这种写法有一个缺陷,来看下面这个模拟代码:

    1 var controller = {
    2     makeRequest(..){
    3         //..
    4         this.makeRequest(..);
    5     }
    6 }
    7 bun.addEventListener("click",controller.makeRequest,false);

    这点代码模拟的是对象方法是被事件触发的,你想想它的this指向了谁?这不用我多说了吧。所以在对象方法需要被执行递归计算的时候最好采用ES5的语法。

     二、计算属性名

    计算属性名起始在ES5中就已经有存在,只是相对ES6的计算属性名来说还是没有达到最简便的方式。计算属性名其实就是使用表达式计算获取对象属性名,先来回忆ES5的计算属性名:

    1 //ES5的计算属性名
    2 var prefix = "user_";
    3 var o = {
    4     baz:function(){}
    5 }
    6 o[prefix + "foo"] = function(){};
    7 o[prefix + "bar"] = function(){};

    ES5中使用计算属性名不能直接写在对象字面量上,而是需要另外采用对象键的方式来实现,而ES6可以直接写在对象字面量上:

    1 var prefix = "user_";
    2 var obj = {
    3     baz:function(){},
    4     [prefix + "foo"] : function(){},
    5     [prefix + "bar"] : function(){}
    6 }

    在对象属性字面这部分,顺便说明一下,ES6标准了[[prototype]]的可以直接使用点的方法添加对象原型属性,但是这个标准化存在着很大的争议,都是这个标准化是为了兼容之前的js代码不得不标准话的语法。

    1 var a = {...}
    2 var obj = {
    3     __proto__:a,
    4     ...
    5 }

     三、模板字面量

     模板字面量有通常被称为模板字符串,也有人说是增强版的字符串,用反引号(`)标识。模板字符串可以当作普通的字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。

     1 //ES6模板字面量语法
     2 // 普通字符串
     3 console.log(`In JavaScript 
     is a line-feed.`); //可以使用
    来实现换行
     4 // 多行字符串,模板可以自动实现换行
     5 console.log( 
     6     `In JavaScript this is
     7 not legal`);
     8 //字符串中嵌入变量
     9 var name = "Bob", time = "today";
    10 console.log(`Hello ${name}, how are you ${time}`);
    11 
    12 //ES5编译结果
    13 console.log("In JavaScript 
     is a line-feed."); 
    14 console.log("In JavaScript this is
    not legal"); 
    15 var name = "Bob",
    16     time = "today";
    17 console.log("Hello ".concat(name, ", how are you ").concat(time)); 

    在模板中可以使用${...}嵌入语法,这样就可以使用模板复用了,因为如果是纯字符的化只能采用字符串拼接“+“,这种写法获取到的是字符串的拼接后的值,而不是拼接表达式,有了模板字面量和${..}嵌入语法就可以实现字符串模板复用。

     1 //ES6插入(嵌入)表达式可以嵌套,并且也可以使用模板
     2 function upper(s){
     3     return s.toUpperCase();
     4 }
     5 var who = "reader";
     6 var text = 
     7 `A rey ${upper("warm")} welcome
     8 to all of you ${upper(`${who}s`)}!`; 
     9 console.log(text);
    10 //ES5的编译结果:
    11 function upper(s) {
    12   return s.toUpperCase();
    13 }
    14 
    15 var who = "reader";
    16 var text = "A rey ".concat(upper("warm"), " welcome
    to all of you ").concat(upper("".concat(who, "s")), "!");
    17 console.log(text);

    关于标签模板字面量作为方法参数使用时,会像字符串字符串一样吗?千万别用模板字面量替代方法的参数,因为使用模板字面量作为方法的实参是一个独立的语法,通常被称为标签模板字面量,来看示例:

     1 function foo(strings, ...values){
     2     console.log(strings),
     3     console.log(values)
     4 }
     5 
     6 function bar(){
     7     return function foo(strings, ...values){
     8         console.log(strings),
     9         console.log(values)
    10     }
    11 }
    12 var desc = "awesome";
    13 foo `Everything is ${desc}!`; 
    14 bar()`Everything is ${desc}!`;
    15 //上面两种执行结果一致
    16 //["Everything is ", "!"]
    17 //["awesome"]

    在标签模板字面量语法中,第一个形参收集的是模板中被嵌入表达式${...}分割的字符串数组,第二个形参要使用“...”语法收集嵌入表达式获取的数据集。关于更多可以了解《你不知道的js》下卷P100~P103

  • 相关阅读:
    spark记录(19)SparkStreaming之从kafkaBroker和zookeeper获取offset,和使用zookeeper管理offset
    spark记录(18)SparkStreaming+kafka receiver和directed模式
    spark记录(17)SparkStreaming checkpoint那些事儿
    spark记录(16)SparkStreaming On HDFS AND TO MySQL
    第三章:使用MYSQL
    第一章:了解SQL
    第零章:安装mysql和导入练习数据
    DjangoRestFramework整体结构---DjangoRestFramework处理一个接口请求的完整流程
    DjangoRestFrameWork整合sentry错误日志服务器
    ubuntu18.04安装错误日志服务器sentry
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11349574.html
Copyright © 2020-2023  润新知