在 ECMAScript 2015 之前,JavaScript 里的对象字面量(也叫对象初始化器)功能很弱。它只能定义两种属性:
令人心痛地,对象字面量的所有用法只用一个简单的例子就能囊括:
1 2 3 4 5 6 7 8 9 10 11 12 |
var myObject = { myString: 'value 1', get myNumber() { return this.myNumber; }, set myNumber(value) { this.myNumber = Number(value); } }; myObject.myString; // => 'value 1' myObject.myNumber = '15'; myObject.myNumber; // => 15 |
JavaScript 是一个基于原型的语言,因此一切皆是对象。当涉及到对象创建、结构和访问原型时,语言必须提供简单的结构。
定义一个对象并设置它的原型是一个常见的任务。我总觉得设置原型应该被对象字面量直接支持,使用单一的语法。
不幸的是,字面量的局限性使得它没有直接的解决方案。你不得不使用Object.create()
来结合对象字面量和设置原型:
1 2 3 4 5 6 7 8 9 |
var myProto = { propertyExists: function(name) { return name in this; } }; var myNumbers = Object.create(myProto); myNumbers['array'] = [1, 6, 7]; myNumbers.propertyExists('array'); // => true myNumbers.propertyExists('collection'); // => false |
在我看来,这是一个不舒服的解决方案。JavaScript 是基于原型的,为什么从原型创建一个对象那么麻烦?
幸运地是,JavaScript 在改变。比较令人沮丧的许多问题在 JavaScript 中正在被一步一步地解决。
这篇文章解释 ES2015 是如何解决上面所说的问题以及改进对象字面量以获得额外的好处::
- 在对象构造的过程中设置原型
- 速记方法定义
- 调用父类方法
- 计算属性名称
同时,让我们看看未来,了解最新的提案(stage 2):对象的 rest 属性和属性展开操作符。
1. 在对象构造时设置原型
如你已经知道得,其中一个访问一个已存在对象的原型的方法是使用 getter 属性__proto__
:
1 2 3 4 5 |
var myObject = { name: 'Hello World!' }; myObject.__proto__; // => {} myObject.__proto__.isPrototypeOf(myObject); // => true |
myObject.__proto__
返回 myObject
的原型对象。
好消息是 ES2015 允许使用 字面量 __proto__
作为属性名来设置对象字面量的原型 { __proto__: protoObject }
。
让我们用 __proto__
重写一下上面那个例子,让它看起来好一点:
1 2 3 4 5 6 7 8 9 10 11 |
var myProto = { propertyExists: function(name) { return name in this; } }; var myNumbers = { __proto__: myProto, array: [1, 6, 7] }; myNumbers.propertyExists('array'); // => true myNumbers.propertyExists('collection'); // => false |
myNumbers
对象使用原型 myProto
创建,这可以通过特殊属性 __proto__
实现。
这个对象通过简单的语句创建,而不需要额外的函数例如 Object.create()
。
如你所见,使用 __proto__
是简单的。我偏爱简单直接的解决方案。
有点说跑题了,回到主题来。我认为获得简单和可靠的解决方案需要通过大量的设计和实践。如果一个解决方案是简单的,你可能认为它同样也很容易被设计出来,然而事实并不是这样:
- 让它变得简单明了的过程是复杂的
- 让它变得复杂和难以理解却很容易
如果某个东西看起来太复杂或者用起来不舒服,很可能它的设计者考虑不周。
元芳,你怎么看?(欢迎在文章底部发表评论参与讨论)
2.1 使用 __proto__
的特例
尽管 __proto__
看似简单,却有一些特殊的场景你需要格外注意。
在对象字面量中 __proto__
只允许使用一次。多次是用的话 JavaScript 会抛出异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var object = { __proto__: {object = { __proto__: { e>{ name1: value }
{ get name(){..} } 以及 setters { set name(val){..} } ,用来设置和获取需要计算的值。令人心痛地,对象字面量的所有用法只用一个简单的例子就能囊括:
定义一个对象并设置它的原型是一个常见的任务。我总觉得设置原型应该被对象字面量直接支持,使用单一的语法。 不幸的是,字面量的局限性使得它没有直接的解决方案。你不得不使用
在我看来,这是一个不舒服的解决方案。JavaScript 是基于原型的,为什么从原型创建一个对象那么麻烦? 幸运地是,JavaScript 在改变。比较令人沮丧的许多问题在 JavaScript 中正在被一步一步地解决。 这篇文章解释 ES2015 是如何解决上面所说的问题以及改进对象字面量以获得额外的好处::
同时,让我们看看未来,了解最新的提案(stage 2):对象的 rest 属性和属性展开操作符。 1. 在对象构造时设置原型如你已经知道得,其中一个访问一个已存在对象的原型的方法是使用 getter 属性
好消息是 ES2015 允许使用 字面量 让我们用
这个对象通过简单的语句创建,而不需要额外的函数例如 如你所见,使用 有点说跑题了,回到主题来。我认为获得简单和可靠的解决方案需要通过大量的设计和实践。如果一个解决方案是简单的,你可能认为它同样也很容易被设计出来,然而事实并不是这样:
如果某个东西看起来太复杂或者用起来不舒服,很可能它的设计者考虑不周。 元芳,你怎么看?(欢迎在文章底部发表评论参与讨论) 2.1 使用
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |