ES6+ 对象的扩展
1. 前言
JavaScript 中对象是非常重要的数据结构,ES6 对对象进行了极大的扩展,使用上也更加简洁。前面我们学习了 扩展语法 和 剩余参数 是对象扩展的其中的一部分,本节和后面几节会对 Object 的扩展进行系统的介绍。后面我们还会学到新的数据结构 Set 和 Map 也是对对象的扩展,另外,还有 Proxy 和 Reflect 也是对象的重大 升级 。本节主要学习以下几点
简洁的 属性 表达 属性 名表达式 方法 的 name 属性 可选链操作符
2. 简洁的 属性 表达
ES6 允许直接写入变量和 函数 ,作为对象的 属性 和 方法
2.1 属性 值简写
在 ES5 中我们知道,在定义对象时 属性 的值是必须要写的,在 ES6 中规定,如果 属性 名和定义的变量名是一样的,就可以在对象中直接写这个变量名作为对象中的一项。如下:
var name = 'imooc' ; // ES5 var obj1 = { name : name , } // ES6 var obj2 = { name , }
上面 代码 中的 obj1 和 obj2 是一样的意思。变量 name 可以直接写在大括号中。这时, 属性 名就是变量名, 属性 值就是变量值。
下面我们来看 一个 在 函数 中返回 一个 对象的实例:
// ES5 function g eto bj ( x , y ) { return { x : x , y : y } ; } // 等同于 ES6 function g eto bj ( x , y ) { return { x , y } ; } g eto bj ( , ) // {x: 1, y: 2}
上面中的 代码 可以看出,在我们平常开发中,组装数据时是非常方便、有用的。
2.2 对象中 方法 的简写
除了 属性 可以简写,对象中的 方法 也是可以简写的,而且更加简洁明了。我们来看下面的例子:
const name = '张三' // ES5 var person = { name : name , getName : function ( ) { console . log ( 'imooc' ) } } ; // ES6 var person = { name , getName ( ) { console . log ( this . name ) } } ; console . log ( person ) // {name: "imooc", getName: ?}
上面的 代码 中,ES5 中定义 一个 对象上的 方法 时需要使用 function 关键字来定义,而 ES6 则直接省略了 冒号和 function 关键字。可以看出使用 ES6 这种简洁的方式更具表达力。
在 Node 中进行模块导出时,这种方式更加方便。我们看下面的例子:
var person = { } ; function getName ( ) { return person . name } function setName ( ) { person . name = '李四' } function clear ( ) { person = { } ; } // ES5 写法 module . exports = { getName : getName setName : setName , clear : clear } ; // ES6写法 module . exports = { getName , setName , clear } ;
上面的 代码 中,我们定义了 一个 person 对象,并向外暴露了若干 方法 用来操作 person 对象,在导出的时候可以看出,ES6 不需要重复地去写变量名,从而更简洁地表达了模块所提供的 方法 。
3. 简洁的 属性 表达
在 JavaScript 中定义对象的 属性 ,一般有两种 方法 。如下:
// 方法 一 obj . name = 'imooc' ; // 方法 二 obj [ 'a' + 'ge' ] = ;
上面的 代码 中, 方法 一直接使用标识符进行赋值操作,这是我们比较常用的赋值操作,但是如果 属性 是 一个 表达式时,则可以使用 方法 二,把表达式写在中括号中。
但是在 ES5 定义字面量对象时不能使用表达式作为字面量对象的 属性 ,只能通过第一种方式(标识符)来定义 属性 。
var obj = { name : 'imooc' , age : }
ES6 对对象的 属性 进行了扩展,可以覆盖更多的场景, 属性 可以使用变量的形式来定义,如下:
var key = 'name' ; var obj = { [ key ] : 'imooc' , [ 'a' + 'ge' ] : }
上面的 代码 中字面量对象中的 属性 是可以放在中括号中,中括号中的可以是变量,也可以是表达式。这无疑是扩展了 属性 的 功能 ,使编程更加灵活。
另外, 属性 也可以是 一个 带空格的字符串,在取值时在中括号中可以直接使用字符串,也可以使用变量。如下:
var str = 'f irs t name' ; var obj = { [ 'I lov e imooc' ] : 'ES6 Wiki' , [ str ] : 'Jack' } console . log ( obj [ 'I lov e imooc' ] ) // ES6 Wiki console . log ( obj [ str ] ) // Jack console . log ( obj [ 'f irs t name' ] ) // Jack
表达式还可以用于定义对象上的 方法 名。
var person = { name : 'Jack' , [ 'get' + 'Name' ] ( ) { console . log ( this . name ) } } ; console . log ( person . getName ( ) ) // Jack
注意 1: 属性 名表达式与 属性 简洁表示,不能同时使用,会报错。
// 报错 var name = 'Jack' ; var age = ; var person = { [ name ] } ; // Uncaught Syntax Error: Unexpected token '}'
上面的 代码 会有语法 错误 ,正确的方式应该是:
var name = 'Jack' ; var person = { [ name ] : } ; // {Jack: 18}
注意 2: 属性 名必须是字符串类型的,如果 属性 表达式是 一个 对象,则会先调 toString() 先将对象转为字符串,然后才进行使用。
var key1 = { name : 'imooc' } ; var key2 = { age : } ; var obj = { [ key1 ] : 'value content 1' , [ key2 ] : 'value content 2' , } console . log ( obj ) // {[object Object]: "value content 2"}
上面 代码 中定义了两个变量都是对象类型的,在 调用 toString() 时会变为 [object Object] 属性 相同。所以,后面的 属性 把前面的覆盖了。
注意 3: 如果 属性 的表达式是数组时,则和对象不一样。数组在 toString() 后会变成 一个 字符串,所以对象 属性 的表达式就是 一个 字符串。
var keys = [ 'imooc' , '7' ] ; var obj = { [ keys ] : 'value content' , } console . log ( key . toString ( ) ) // "imooc,7" console . log ( obj ) // {imooc,7: "value content"} console . log ( obj [ keys ] ) // "value content"
上面的 代码 中可以看出来,数组 keys 在 toString() 得到了 imooc,7 作为 obj 的 属性 。另外,我们也可以直接使用 keys 获取 obj 对象上的值。
4. 方法 的 name 属性
你有没有想过怎么 获取 对象上 方法 的名字?ES6 增加 了 函数 的 name 属性 , 函数 直接 调用 name 会返回 函数 名。字面量对象上的 方法 也是 函数 ,因此也有 name 属性 。如下实例:
var person = { name : "Jack" , getName ( ) { console . log ( this . name ) ; } , } ; person . getName . name // "getName"
上面 代码 中, getName() 方法 的 name 属性 返回 函数 名(即 方法 名)
有两种特殊情况:
Function 构造 函数 创造的 函数 , name 属性 返回 “anonymous”; bind 方法 创造的 函数 , name 属性 返回 “bound” 加上 原 函数 的名字。
( new Function ( ) ) . name // "anonymous" var doSomething = function ( ) { // t odo } ; doSomething . bind ( ) . name // "bound doSomething"
如果对象的 方法 是 一个 Symbol 值,那么 name 属性 返回的是带中括号的 Symbol 的描述 内容 。
const key1 = Symbol ( 'description content' ) ; const key2 = Symbol ( ) ; let obj = { [ key1 ] ( ) { } , [ key2 ] ( ) { } , } ; obj [ key1 ] . name // "[description content]" obj [ key2 ] . name // ""
5. 小结
本节介绍了 ES6 的对象扩展 内容 ,学习了对象中 属性 和 方法 的简写、 属性 的表达式以及注意的 内容 。最后学习了 函数 的 name 属性 ,可以返回 函数 名。