该材料(译文,我们提醒您注意)专用于研究JavaScript中对象文字的功能,尤其是ECMAScript标准的最新版本中出现的创新。
JavaScript具有使用对象文字创建对象的强大而便捷的功能。 ES2015(ES6)标准简化了为现代浏览器(IE除外)和Node.js平台创建应用程序时使用对象的工作。

基础知识
用某些语言创建对象可能会占用大量资源,这意味着程序员的工作时间和系统的计算资源。 特别是,我们谈论的事实是,在创建对象之前,必须先描述类(例如,使用
class
关键字)。 在JavaScript中,可以快速,轻松地创建对象,而无需任何初步步骤。 考虑一个例子:
// ES5 var myObject = { prop1: 'hello', prop2: 'world', output: function() { console.log(this.prop1 + ' ' + this.prop2); } }; myObject.output(); // hello world
在编程中,经常使用“一次性”对象。 它们存储设置和其他数据,它们用作函数的参数,函数返回的值以及其他情况。 在这种情况下,JavaScript对象文字非常有用,ES6扩展了它们的功能。
变量初始化对象
对象的属性通常是通过为变量分配与它们已经分配的名称相同的名称来创建的。 例如:
在ES6中,您不再需要重复变量名:
当使用“显示
模块”模式时,此技术可能对返回的对象很有用,该模式允许您为各种代码片段创建名称空间,以避免名称冲突。 例如:
// ES6 const lib = (() => { function sum(a, b) { return a + b; } function mult(a, b) { return a * b; } return { sum, mult }; }()); console.log( lib.sum(2, 3) ); // 5 console.log( lib.mult(2, 3) ); // 6
您可能已经了解了ES6模块中如何使用此技术:
// lib.js function sum(a, b) { return a + b; } function mult(a, b) { return a * b; } export { sum, mult };
声明对象方法的简写语法
在ES5中声明对象方法时,必须使用
function
关键字:
// ES5 var lib = { sum: function(a, b) { return a + b; }, mult: function(a, b) { return a * b; } }; console.log( lib.sum(2, 3) ); // 5 console.log( lib.mult(2, 3) ); // 6
现在,在ES6中,您将无法再执行此操作。 以下是声明方法的简便方法:
// ES6 const lib = { sum(a, b) { return a + b; }, mult(a, b) { return a * b; } }; console.log( lib.sum(2, 3) ); // 5 console.log( lib.mult(2, 3) ); // 6
应该注意的是,由于方法必须具有名称,因此此处不能使用ES6箭头函数(
=>
)。 但是,如果您为方法显式分配名称(如ES5),则可以使用箭头功能。 例如:
// ES6 const lib = { sum: (a, b) => a + b, mult: (a, b) => a * b }; console.log( lib.sum(2, 3) ); // 5 console.log( lib.mult(2, 3) ); // 6
动态键
在ES5中,尽管可以在创建对象后添加名称为变量的键,但是不能将变量用作键名。 例如:
// ES5 var key1 = 'one', obj = { two: 2, three: 3 }; obj[key1] = 1; // obj.one = 1, obj.two = 2, obj.three = 3
在ES6中,可以通过在方括号(
[]
)中放置名称表达式来动态分配键。 例如:
// ES6 const key1 = 'one', obj = { [key1]: 1, two: 2, three: 3 }; // obj.one = 1, obj.two = 2, obj.three = 3
要创建密钥,可以使用任何表达式:
// ES6 const i = 1, obj = { ['i' + i]: i }; console.log(obj.i1); // 1
动态键可用于方法和属性:
// ES6 const i = 2, obj = { ['mult' + i]: x => x * i }; console.log( obj.mult2(5) ); // 10
另一个问题是是否使用动态生成的名称创建属性和方法。 使用此技术的代码的可读性可能会下降。 也许,如果您面临动态名称似乎合适的情况,最好考虑使用工厂函数或类来创建对象。
改制
解构是对象属性的提取及其对变量的分配。 通常,在应用程序开发期间,您需要提取对象属性的值并将其写入变量。 在ES5中,您必须使用属性访问命令对此进行如下描述:
// ES5 var myObject = { one: 'a', two: 'b', three: 'c' }; var one = myObject.one, // 'a' two = myObject.two, // 'b' three = myObject.three; // 'c'
ES6支持解构。 您可以创建一个具有该对象相应属性的同名变量,然后执行以下操作:
// ES6 const myObject = { one: 'a', two: 'b', three: 'c' }; const { one, two, three } = myObject; // one = 'a', two = 'b', three = 'c'
对象属性值所属的变量实际上可以具有任何名称,但是如果它们与属性名称不同,则必须使用
{ propertyName: newVariable }
:
// ES6 const myObject = { one: 'a', two: 'b', three: 'c' }; const { one: first, two: second, three: third } = myObject; // first = 'a', second = 'b', third = 'c'
具有复杂结构的对象(其中嵌入了数组和其他对象)也可以用于破坏性分配操作中:
// ES6 const meta = { title: 'Enhanced Object Literals', pageinfo: { url: 'https://www.sitepoint.com/', description: 'How to use object literals in ES2015 (ES6).', keywords: 'javascript, object, literal' } }; const { title : doc, pageinfo: { keywords: topic } } = meta; /* doc = 'Enhanced Object Literals' topic = 'javascript, object, literal' */
乍一看,所有这一切似乎都很复杂,但是要弄清楚它并不难,主要是要记住以下几点:
- 表达式的右侧是数据源-存储要检索的数据的数组或对象。
- 表达式的左侧是破坏性分配的目标-一种描述将向变量分配从数组或对象提取的值的结构。
使用解构时,您可能会遇到一些困难。 因此,表达式不能以花括号开头,因为这样看起来就象一段代码。 例如:
{ a, b, c } = myObject;
声明变量时,系统通常会意识到这种设计:
const = myObject;
如果已经声明了变量,则必须将表达式括在括号中:
let a, b, c; ({ a, b, c } = myObject);
因此,在处理销毁时,您应该注意代码,而不要混合使用声明和未声明的变量。
分解是一种可以在许多情况下派上用场的技术。
默认功能参数
如果函数需要一长串参数,通常将带有参数的单个对象传递给它更容易。 例如:
prettyPrint( { title: 'Enhanced Object Literals', publisher: { name: 'SitePoint', url: 'https://www.sitepoint.com/' } } );
在ES5中,必须解析带有参数的对象,以便在这些对象没有所需的对象时,为相应的参数分配默认值:
// ES5, function prettyPrint(param) { param = param || {}; var pubTitle = param.title || 'No title', pubName = (param.publisher && param.publisher.name) || 'No publisher'; return pubTitle + ', ' + pubName; }
在ES6中,可以为任何参数分配默认值:
// ES6 - function prettyPrint(param = {}) { ... }
然后,您可以使用解构从对象中提取值,并在必要时分配默认值:
// ES6 function prettyPrint( { title: pubTitle = 'No title', publisher: { name: pubName = 'No publisher' } } = {} ) { return `${pubTitle}, ${pubName}`; }
值得注意的是,尽管这是程序员个人喜好的问题,但这种代码可能比传统代码更难阅读。
解析函数返回的对象
函数只能返回一个值,但是此值可以是具有数百个属性或方法的对象。 在ES5中,您首先必须获取返回的对象,然后可以从中提取值:
重组简化了这一过程。 现在,无需将对象保存在单独的变量中然后解析它,就可以完成所有这些操作:
您可能已经在Node.js中看到了类似的内容。 例如,如果只需要
fs
模块的
readFile()
和
writeFile()
方法,则可以像这样获得指向它们的链接:
// ES6 Node.js const { readFile, writeFile } = require('fs'); readFile('file.txt', (err, data) => { console.log(err || data); }); writeFile('new.txt', 'new content', err => { console.log(err || 'file written'); });
剩余参数语法和扩展运算符ES2018(ES9)
=在ES2015中,仅当使用数组时,才使用其余参数和扩展运算符的语法(都看起来像三个点,
…
)。 在ES2018中,类似的功能可用于处理对象:
const myObject = ; const = myObject;
可以使用类似的方法将某些值传输到函数:
function restParam({ a, ...x }) {
请注意,在这种情况下,您只能使用一个在列表末尾带有三个点的表达式。 另外,对于嵌套在其他对象中的对象,此操作无效。
扩展运算符可以在对象内部使用:
const obj1 = , obj2 = ;
扩展运算符可用于克隆对象(
obj2 = { ...obj1 };
),但是在此必须牢记,使用这种方法将执行对象的浅表复制。 如果对象的属性是其他对象,则对象的克隆将引用相同的嵌套对象。
其余参数和扩展运算符的语法尚未得到广泛支持。 当前,它们可以在Chrome和Firefox浏览器中使用,而无需进行额外的努力,也可以在为Node.js平台8.6和更高版本开发时使用。
总结
对象文字一直是有用的JavaScript功能。 自ES2015标准以来,JavaScript中出现的创新并没有带来根本的变化,但是它们节省了程序员的时间,并有助于编写更简洁的代码。
亲爱的读者们! 您最常使用哪些创建JS对象的方法?
