概览

对象属性的简洁表示法

ES6容许间接写入变量和函数作为对象的属性和办法。
ES6容许在对象中只写属性名,不写属性值。
let foo = 'bar';let baz = {foo};console.log(baz); // {foo:'bar'}// same aslet baz1 = {foo:foo}console.log(baz1); // {foo:'bar'}let first = 'Jone';let last = 'Doe';let obj = {first,last};console.log(obj); // {first: "Jone", last: "Doe"}// same aslet obj1 = {first:first,last:last};console.log(obj1); // {first: "Jone", last: "Doe"}const HELLO = {  method(){    return 'hello'  }}console.log(HELLO.method()); // 'hello'// same asconst HELLO1 = {  method:function(){    return 'hello'  }}console.log(HELLO1.method()); // 'hello'

理论使用中的一些例子:

// 用于人物名称及行为的对象let birth = '2000/01/01'const PERSON = {  name: '张三',  birth, // same as: birth:birth  hello() {console.log('我的名字是', this.name);}  // same as: hello:function(){...}}// 用于函数返回值function getPoint(x = 1, y=10){  return {x, y}}console.log(getPoint()); // {x: 1, y: 10}console.log(getPoint(3,3)); // {x: 3, y: 3}console.log(getPoint(3)); // {x: 3, y: 10}// CommonJS模块输入变量let ms = {};function getItem(key){  return key in ms? ms[key] : null;}function setItem(key,value){  ms[key] = value;}function clear(){  ms = {};}module.exports = {getItem,setItem,clear};// same as: module.exports = {getItem:getItem,setItem:setItem,clear:clear};// 属性的赋值器和取值器const CART = {  _wheels: 4,  get wheels(){    return this._wheels;  },  set wheels(value){    if(value<this._wheels){      throw new Error('数值太小了');    }    this._wheels = value;  }}

属性名表达式

ES6容许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内。

定义对象属性的两种办法:

  • 通过固定名称

    let obj = {};obj.foo = true;console.log(obj); // {foo: true}
  • 通过表达式

    let obj1 = {};obj1['a'+'bc'] = 123;console.log(obj1); // {abc: 123}
let propKey = 'foo';let propKeyObj = {  [propKey]: true,  ['a'+ 'bc']: 123}console.log(propKeyObj); // {foo: true, abc: 123}let lastWord = 'last word';let a = {  'first word':'hello',  [lastWord]:'world'}console.log(a); // {first word: "hello", last word: "world"}console.log(a['first word']);// 'hello'console.log(a[lastWord]); // 'world'console.log(a['last word']); // 'world'// 定义方法名let methodName = {  ['h'+'ello'](){    return 'hi'  }}console.log(methodName.hello()); // 'hi'

留神:属性名表达式不能和简洁表达式同时应用

// 报错let foo = 'bar';let bar = 'abc';let baz = {[foo]};

留神:属性表达式如果是一个对象,默认状况下会把对象转为字符串[object Object]

const keyA = {a:1};const keyB = {b:2};const myObject = {  [keyA]: 'valueA',  [keyB]: 'valueB',}console.log(myObject); // {[object Object]: "valueB"}

Object.is(value1,value2)

与严格相等运算符(===)的行为基本一致;
解决严格运算符(===)NaN不等于本身,以及+0等于-0的问题。
console.log(Object.is('foo','foo'));; // trueconsole.log({} === {}); // falseconsole.log(Object.is({},{})); // falseconsole.log(NaN === NaN); // falseconsole.log(Object.is(NaN,NaN)); // trueconsole.log(+0 === -0); // trueconsole.log(Object.is(+0,-0)); // falseconsole.log([0,NaN,2].indexOf(NaN)); // -1console.log([0,NaN,2].findIndex(x => Object.is(x, NaN))); // 1

Object.assign(target,source_1,source_2,...)

Object.assign()办法将源对象(source)所有可枚举的属性合并到指标对象(target)中:它批改target,首先将source_1的所有可枚举的本人的属性复制到target中,而后将source_2的所有本人的属性复制到target中,以此类推。最初,它返回target。
let target = {a:1};let source_1 = {b:2};let source_2 = {c:3};Object.assign(target,source_1,source_2);console.log(target,source_1,source_2); // {a: 1, b: 2, c: 3} {b: 2} {c: 3}

让咱们更认真看看Object.assign()是如何运作的:

  • 两种类型的属性键:同时反对StringSymbel作为属性键;

    let v1 = 'abc';let v2 = true;let v3 = 10;let v4 = {[Symbol('c')]: 'c'};const obj = Object.assign({}, v1, v2, v3, v4);console.log(obj); // {0: "a", 1: "b", 2: "c", Symbol(c): "c"}
  • 仅复制源对象可枚举的本身属性:不复制继承属性,也不复制不可枚举的属性;

    const obj = Object.assign({b: 'c'},    Object.defineProperty({}, 'invisible',{      enumerable:false, // enumerable属性称为‘可枚举性’      value:'hello'    }))console.log(obj); // {b: "c"}
  • 通过赋值复制:指标对象中的属性是通过赋值(外部操作[[Put]])创立的。这意味着,如果target领有(本人的或继承的)setter,则在复制期间将调用这些setter。另一种办法是定义新的属性,这是一种总是创立新的本人的属性且从不调用setter的操作。最后有人倡议应用Object.assign()的一个变体,它应用定义而不是赋值的形式。这个提议在ECMAScript 6中曾经被回绝了,然而在当前的版本中可能会被重新考虑。

    let obj1 = {a: {b: 1}};let obj2 = Object.assign({}, obj1);console.log(obj2); // {a: {b: 1}} 

// Object.assign()办法履行的是浅复制,而不是深复制。
let target = {a: { b: 'c', d: 'e' }};
let source = {a: { b: 'hello' }};
const obj = Object.assign(target, source);
console.log(obj); // a: {b: "hello"}
console.log(target); // a: {b: "hello"}

常见用处:  **为对象增加属性**  

class Point{
constructor(x, y){

Object.assign(this, {x, y});

}
}

**为对象增加办法**  

function SomeClass(){

}
Object.assign(SomeClass.prototype, {
someMethod(arg1,arg2){

// ...

},
anotherMethod(){

// ...

}
})
console.dir(SomeClass);

// same as
SomeClass.prototype.someMethod = function(arg1, arg2){
//...
};
SomeClass.prototype.anotherMethod = function(){
//...
}

**克隆对象**  

// 克隆原始对象本身的值
function clone1(origin){
return Object.assign({}, origin);
}

// 克隆原始对象继承的值(放弃继承链)
function clone2(params) {
let paramsProto = Object.getPrototypeOf(params);
return Object.assigin(Object.create(paramsProto), params)
}

**合并多个对象**

// 多个对象合并到target
const merge1 = (target, ...sources) => Object.assign(target, ...sources);
// 多对象合并返回新对象
const merge2 = (...sources) => Object.assign({}, ...sources);

**为属性指定默认值**  

const DEFAULTS = {
logLevel: 0,
output: 'html'
};
function processContent(options){
options = Object.assign({},DEFAULTS,options);
console.log(options);
}
processContent('abc'); // {0: "a", 1: "b", 2: "c", logLevel: 0, output: "html"}
processContent({'abc':'abc'}); // {logLevel: 0, output: "html", abc: "abc"}

### 属性的遍历  > `for...in`、`Object.keys(obj)`、`Object.getOwnPropertyNames(obj)`、`Object.getOwnPropertySymbels(obj)`、`Reflect.ownKeys(obj)`  

function allObj(){
this.name = '张三'; // 自有属性
this.age = '12'; // 自有属性
this.invisible = {

enumerable: false,value: 'hello'

},
this.invisible = {

enumerable: false,value: 'hello'

}
}
allObj.prototype.disEnum = {
enumerable: false,
value: 'disEnum'
}
allObj.prototype.Enum = {
enumerable: true,
value: 'Enum'
}
let obj = new allObj
Object.assign(obj, {
a: '1',
b: '2',
c: '3',

})
// let obj2 = Object.assign(obj1,
// Object.defineProperty({}, )
// )
Object.assign(obj,
Object.defineProperty({}, 'visible',{

enumerable: true,value: 'word'

})
)
console.log(obj); // allObj {a: "1",age: "12",b: "2",c: "3",invisible: {enumerable: false,value: 'hello'},name: "张三",visible: "word",Symbol(c): "c",__proto__:Enum: {enumerable: true, value: "Enum"},disEnum: {enumerable: false, value: "disEnum"}}
// for...in循环遍历对象本身的和继承的属性(不含Symbol属性)
for(let key in obj){
console.log(key);
// name
// age
// invisible
// a
// b
// c
// invisible
// visible
// disEnum
// Enum
}

// Object.keys()返回一个数组,包含对象本身(不含继承的)的所有属性(不含Symbol属性)
console.log(Object.keys(obj)); // ["name", "age", "invisible", "a", "b", "c", "visible"]

// Object.getOwnPropertyNames返回一个数组,蕴含对象本身的所有属性(不含Symbol属性,然而包含不可枚举属性 )
console.log(Object.getOwnPropertyNames(obj)); // ["name", "age", "invisible", "a", "b", "c", "visible"]

// Object.getOwnPropertySymbols() 返回一个数组,蕴含所有对象本身的所有Symbol属性
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(c)]

// Reflect.ownKeys()返回一个数组,蕴含对象本身的所有属性,不论属性名是Symbol还是字符串,也不论是否可枚举
console.log(Reflect.ownKeys(obj)); // ["name", "age", "invisible", "a", "b", "c", "visible", Symbol(c)]