属性的简洁表示
es6 允许直接写入和函数作为对象的属性和方法。
var foo = 'bar';var baz = {foo};baz // {foo: "bar"}复制代码
等同于
var baz = { foo: "bar"}复制代码
es6允许,在对象中只写属性名,不写属性值。这时属性值等于属性名所代表的变量。
function f(x, y){ return {x, y};}复制代码
等同与
function f(x, y){ return { x:x,y:y};}f(1,2); //{x:1,y:2}复制代码
除了属性简写,方法也可以简写。
var o = { method() { return 'hello'; }}复制代码
等同
var o = { method: function() { return "hello"; }}复制代码
用于函数返回值
function getPoint() { var x =1; var y = 10; return {x,y}}getPoint();// {x:1,y:10}复制代码
CommonJS模块输出非常适合简洁写法
var ms = {};function getItem (key) { return key in ms ? ms[key] : null;}function setItem (key) { ms[key] = value;}function clear (){ ms = {};}module.exports = { getItem, setItem, clear};复制代码
属性名表达式
定义对象属性有两种方法
//1 直接用标识符作为属性名obj.foo = true;//2 表达式作为属性名obj['a' + 'bc'] = 123;复制代码
ES6允许字面量定义方法时,把表达式放在方括号内。
let propKey = 'foo'let obj = { [propKey] : true, ['a' + 'bc'] : 123}复制代码
表达式还可以用于定义方法名
let obj = { ['h' + 'ello']() { return 'hi'; }}obj.hello(); //hi复制代码
属性表达式与简介表示法,不能同时使用,否则会报错。
// 报错var foo = 'bar';var bar = 'abc';var baz = {[foo]}// 正确var foo = 'bar';var baz = {[foo]:'abc'}复制代码
方法的name属性
函数的name属性返回函数名,对象方法也是函数,也有name。
const person = { sayName() { console.log('hello!'); }}person.sayName.name //"sayName"复制代码
上述代码,name属性返回函数名,即方法名。
如果对象的方法使用了取值函数(getter)和存值函数(setter),则name属性不在该方法上,而是在该方法属性的描述对象的get和set属性上,返回值是方法名前加上get和set。
const obj = { get foo(){}, set foo(x){}}obj.foo.name //找不到nameconst descriptor = Object.getOwnPropertyDescriptor(obj,'foo');descriptor.get.name //"get foo"descriptor.set.name //"set foo"复制代码
Object.is()
ES5比较两个值相等,有== 和 ===,都有缺点,前者会自动转换数据类型,后者NaN不等于自身,以及 +0 等于 -0 ,JavaScript缺乏这样一种运算,在所有环境中,只要两个值是一样的,就应该相等。
ES6 提出了“same-value equally”(同值相等)算法用来解决这个问题。Object.is 就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格相等(===)行为基本一致。
Object.is('foo','foo') //trueObject.is({},{}) //false复制代码
不同之处,有两个
+0 === -0 //trueNaN === NaN //falseObject.is(+0,-0) // falseObject.is(NaN,NaN)//true复制代码
ES5部署代码
Object.defineProperty(Object,'is',{ value: function(x, y){ if(x === y){ // 针对+0 不等于 -0 return x !== 0 || 1 / x === 1 / y } // 针对NaN return x !== x && y !== y }, configurable: true, enumerable: false, writable: true});复制代码
Object.assign()
Object.assign() 用于向所有可枚举属性复制到目标对象。
var target = { a:1};var source1 = { b:2};var source2 = { c:3};Object.assign(target,source1,source2);target // {a:1,b:2,c:3}复制代码
Object.assign 第一个参数是目标对象,后面的参数都是源对象。
如果目标对象与源对象有相同属性名,后面的属性会覆盖前面的属性。
Object.assign 复制,只复制源对象的自身属性,不复制继承属性,也不可复制不可枚举属性。属性名为Symbol值的属性,也会被复制。
Object.assign 实行的是浅复制,不是深复制。如果源对象某个属性值是对象,那么,目标对象复制得到的是对这个对象的引用。
var target = { a:{ b:'c', d:'e' }}var source = { a:{ b:'hello' }}Object.assign(target, source); //{a:{b:'hello'}}复制代码
数组注意点:
Object.assign([1,2,3],[4,5]) //[4,5,3]复制代码
上面代码,Object.assign把数组视为属性名为 0 1 2的对象,因此目标数组的 0号属性4覆盖了原数组的0号属性1.
常见用途
为对象添加属性
将 x,y属性添加到Point类对象实例中。
class Point { constructor(x,y){ Object.assign(this,{x,y}) }}复制代码
为对象添加方法
Object.assign(SomeClass.prototype,{ someMethod(arg1,arg2){ ... }, anotherMethod(){ ... }});//等同于SomeClass.prototype.someMethod = function (arg1,arg2){ ...}SomeClass.prototype.anotherMethod = function (){ ...}复制代码
克隆对象
只能克隆原始对象自身的值,不能克隆继承的值。
function clone(origin) { return Object.assign({},origin)}复制代码
想要保持继承,使用如下代码
function clone(origin){ let originProto = Object.getPrototypeOf(origin); return Object.assign(Object.create(originProto),origin)}复制代码
合并多个对象
将多个对象合并到某个对象
const merge = (target,...sources) => Object.assign(target,...sources);复制代码
属性的可枚举
对于每一个属性都具有一个描述对象,用于控制该属性的行为。
Object.getOwnPropertyDescriptor 方法可以获取该属性的描述对象。
let obj = { foo:123}Object.getOwnPropertyDescriptor(obj,'foo');//{ // value:123,// writable:true,// enumerable:true// configurable:true//}复制代码
描述对象的 enumerable 属性,称为“可枚举性”。如果该属性为false,表示某些操作会忽略当前属性。
ES5 有三个操作会忽略 enumerable 为 false 的属性。
- for...in循环:只遍历对象自身的和继承的可枚举属性。
- Object.keys():返回对象自身的所有可枚举属性的键名。
- JSON.stringify():只串行化对象自身的可枚举属性。
总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性,所以,尽量不要用 for...in循环,而用 Object.key()代替。
属性的遍历
一共 5 种方法可遍历对象的属性。
1 for...in
遍历对象自身的和继承的可枚举属性
2 Object.keys(obj)
Object.keys 返回一个数组,包括对象自身的(不含继承)所有可枚举(不含Symbol属性)
3 Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames(obj) 返回一个数组,包含对象自身所有属性(不含Symbol属性,但是包括不可枚举属性)
4 Object.getOwnPropertySymbol(obj)
Object.getOwnPropertySymbol(obj) 返回一个数组,包含对象自身所有的Symbol属性。
5 Reflect.ownKeys(obj)
Reflect.ownKeys(obj) 返回一个数组,包含对象自身的所有属性,不管是Symbol还是字符串,也不管是否可枚举。