ES6中的对象与字符串

ES5的Getter/Setter

ES5中定义了 getter/setter 的字面量形式,但是使用的并不广泛。随着ES6的普及,相信 getter/setter 的语法会得到更广泛的使用,所以在这里介绍这个并不属于ES6的特性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var o = {
__id: 10,
get id() { return this.__id++; },
set id(v) { this.__id = v; }
}

o.id; // 10
o.id; // 11
o.id = 20;
o.id; // 20

// and:
o.__id; // 21
o.__id; // 21 -- still!

计算属性名

你应该很可能遇到过,对象属性名需要进行字符串操作得到:

1
2
3
4
5
6
7
8
var prefix = "user_";

var o = {
baz: function(..){ .. }
};

o[ prefix + "foo" ] = function(..){ .. };
o[ prefix + "bar" ] = function(..){ .. };

ES6中新增了对象定义的语法,你可以直接在对象的声明中进行字符串的操作:

1
2
3
4
5
6
7
8
var prefix = "user_";

var o = {
baz: function(..){ .. },
[ prefix + "foo" ]: function(..){ .. },
[ prefix + "bar" ]: function(..){ .. }
..
};

任何有效的表达式都可以出现在 [..] 中,计算的结果成为对象的属性名。

计算属性名同样可以出现在简洁的方法或者generator声明中:

1
2
3
4
var o = {
["f" + "oo"]() { .. } // computed concise method
*["b" + "ar"]() { .. } // computed concise generator
};

设置原型([[Prototype]])

在ES6中可以通过 Object.setPrototypeOf(..) 设置对象的原型,例如:

1
2
3
4
5
6
7
8
9
var o1 = {
// ..
};

var o2 = {
// ..
};

Object.setPrototypeOf( o2, o1 );

super 对象

super 是与对象相关的,而JS是基于原型的语言,虽然如此, super 对JS来说还是很有用的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var o1 = {
foo() {
console.log( "o1:foo" );
}
};

var o2 = {
foo() {
super.foo();
console.log( "o2:foo" );
}
};

Object.setPrototypeOf( o2, o1 );

o2.foo(); // o1:foo
// o2:foo

注意: super 只能在简洁声明方式的函数中有用,它的使用方式是 super.XXX() 而不是 super()

模板字面量

这里的模板与模板引擎(例如Handlebars ,Jade等)的模板含义并不相同,这里的模板字面量可以理解为插入字符串字面量。

相信大家都熟悉通过 "" 或者 '' 来声明字符串的方式, 如果有变量要插入字符串当中,只能通过字符串的拼接来实现。

ES6中引入了一个新的字符串字面量定义方式,使用 ` 符号。这样定义的字符串允许插入表达式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// old way
var name = "Kyle";

var greeting = "Hello " + name + "!";

console.log( greeting ); // "Hello Kyle!"
console.log( typeof greeting ); // "string"

// new way
var name = "Kyle";

var greeting = `Hello ${name}!`;

console.log( greeting ); // "Hello Kyle!"
console.log( typeof greeting ); // "string"

使用 ${..} 将表达式插入,表达式的结果会自动的计算,最后得到的是一个字符串。可以利用模板字面量实现多行文本的输入

1
2
3
4
5
6
7
8
9
var text =
`Now is the time for all good men
to come to the aid of their
country!`;


console.log( text );
// Now is the time for all good men
// to come to the aid of their
// country!

标签模板字面量

这是ES6提供的一个非常酷的特性,刚开始见到的适合可能会有些不适应,但是非常有用:

1
2
3
4
5
6
7
8
9
10
function foo(strings, ...values) {
console.log( strings );
console.log( values );
}

var desc = "awesome";

foo`Everything is ${desc}!`;
// [ "Everything is ", "!"]
// [ "awesome" ]

这里的foo函数调用并没有用到 () 操作符。在模板字面量之前的标签 foo 是一个函数。实际上,这个位置可以是任意返回函数的一个表达式,例如:

1
2
3
4
5
6
7
8
9
10
11
12
function bar() {
return function foo(strings, ...values) {
console.log( strings );
console.log( values );
}
}

var desc = "awesome";

bar()`Everything is ${desc}!`;
// [ "Everything is ", "!"]
// [ "awesome" ]

那么 foo 函数到底传了什么参数进去呢?

第一个参数叫做 strings 是一个字符串数组(插入表达式之间的东西),这里我们得到的是 "Everything is""!"

然后,例子当中将其他传入参数折叠到一个参数 values 里面。

使用标签模板字面量,可以在得到最终的拼接字符串之前,对字符串进行一个处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function dollabillsyall(strings, ...values) {
return strings.reduce( function(s,v,idx){
if (idx > 0) {
if (typeof values[idx-1] == "number") {
// look, also using interpolated
// string literals!
s += `$${values[idx-1].toFixed( 2 )}`;
}
else {
s += values[idx-1];
}
}

return s + v;
}, "" );
}

var amt1 = 11.99,
amt2 = amt1 * 1.08,
name = "Kyle";

var text = dollabillsyall
`Thanks for your purchase, ${name}! Your
product cost was ${amt1}, which with tax
comes out to ${amt2}.`


console.log( text );
// Thanks for your purchase, Kyle! Your
// product cost was $11.99, which with tax
// comes out to $12.95.

原生字符串

ES6 提供了一个内建的函数String.row() ,可以得到字符串的字面量的原生版本:

1
2
3
4
5
6
7
8
9
console.log( `Hello\nWorld` );
// Hello
// World

console.log( String.raw`Hello\nWorld` );
// Hello\nWorld

String.raw`Hello\nWorld`.length;
// 12

总结

本文是ES6中字符串和对象新内容的简述,包括对象的计算属性名,原型的设置,以super对象。还介绍了ES6中的模板字符串,以及标签模板字符串和如何得到原生字符串。