这节课学习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'