Object的常用方法

Object的常用方法

Posted by EWL on July 22, 2018

Object的常用方法

Object.assign(target, …source)

参数:target表示目标对象,source表示源对象群组 返回值:目标对象。

复制一个简单对象
//复制一个对象
let obj = {
    name: 'name',
    age: 22,
    job: 'engineer',
};
let obj01 = {
    name: 'name01'
};
console.log(Object.assign(obj, obj01));//obj01的name属性会覆盖掉obj的name属性,目标对象是会改变的
复制一个属性值为对象引用的稍复杂对象
//假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。
//修改其中一个对象的属性值,会使得所有的引用都改变
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign(obj1);
console.log(obj1);//{a:0, b:{c:3}}
console.log(obj2);//{a:0, b:{c:3}}
obj2.b.c = 3;
console.log(obj2);//{a:0, b:{c:3}}
console.log(obj1);//{a:0, b:{c:3}}
合并多个对象
//合并对象
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
合并具有相同属性的对象

var o1 = { a: 1, b: 1, c: 1 };
var o2 = { b: 2, c: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
特殊情况(继承属性和不可枚举属性不能被拷贝)

var obj = Object.create({foo: 1}, { // foo 是个继承属性。
    bar: {
        value: 2  // bar 是个不可枚举属性。
    },
    baz: {
        value: 3,
        enumerable: true  // baz 是个自身可枚举属性。
    }
});

var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }
复制原始类型(强制转换以及会被忽略的值)
//原始类型会被包装成对象,数字也会被忽略
var v1 = "abc";
var v2 = true;
var v3 = 10;
var v4 = Symbol("foo")

var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); 
// 原始类型会被包装,null 和 undefined 会被忽略。
// 注意,只有字符串的包装对象才可能有自身可枚举属性。
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
遇到异常情况,assign方法会暂停退出
//首先,只读属性不能被覆盖,其次遇到异常之后assign方法就会退出不会继续进行
var target = Object.defineProperty({}, "foo", {
    value: 1,
    writable: false
}); // target 的 foo 属性是个只读属性。

Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
// TypeError: "foo" is read-only
// 注意这个异常是在拷贝第二个源对象的第二个属性时发生的。

console.log(target.bar);  // 2,说明第一个源对象拷贝成功了。
console.log(target.foo2); // 3,说明第二个源对象的第一个属性也拷贝成功了。
console.log(target.foo);  // 1,只读属性不能被覆盖,所以第二个源对象的第二个属性拷贝失败了。
console.log(target.foo3); // undefined,异常之后 assign 方法就退出了,第三个属性是不会被拷贝到的。
console.log(target.baz);  // undefined,第三个源对象更是不会被拷贝到的。
Object.create(proto, [propertiesObject])

参数: proto表示新创建对象的原型对象 propertiesObject可选。如果没有指定为 undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。

返回值:一个新对象,带着指定的原型对象和属性。 错误: 如果propertiesObject参数不是 null 或一个对象,则抛出一个 TypeError 异常。

完成类的继承
// Shape - 父类(superclass)
function Shape() {
  this.x = 0;
  this.y = 0;
}

// 父类的方法
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - 子类(subclass)
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?',
  rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
  rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'

解析: 首先可以画出原型链,只要Rectangle和Shape在rect.__proto__所在的原型链上,那么就可以得出true的结论。

为第二个参数配置合适属性
//加入第二个参数,参数必须写明是否可配置可写可枚举,否则都是默认为false
var o;

// 创建一个原型为null的空对象
o = Object.create(null);


o = {};
// 以字面量方式创建的空对象就相当于:
o = Object.create(Object.prototype);


o = Object.create(Object.prototype, {
  // foo会成为所创建对象的数据属性
  foo: { 
    writable:true,
    configurable:true,
    value: "hello" 
  },
  // bar会成为所创建对象的访问器属性
  bar: {
    configurable: false,
    get: function() { return 10 },
    set: function(value) {
      console.log("Setting `o.bar` to", value);
    }
  }
});


function Constructor(){}
o = new Constructor();
// 上面的一句就相当于:
o = Object.create(Constructor.prototype);
// 当然,如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码


// 创建一个以另一个空对象为原型,且拥有一个属性p的对象
o = Object.create({}, { p: { value: 42 } })

// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
o.p = 24
o.p
//42

o.q = 12
for (var prop in o) {
   console.log(prop)
}
//"q"

delete o.p
//false

//创建一个可写的,可枚举的,可配置的属性p
o2 = Object.create({}, {
  p: {
    value: 42, 
    writable: true,
    enumerable: true,
    configurable: true 
  } 
});
Object.keys(obj)

参数: 要返回其枚举自身属性的对象 返回值: 一个表示给定对象的所有可枚举属性的字符串数组

枚举各类引用类型的属性
// simple array
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']

// array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']

// getFoo is a property which isn't enumerable
var myObj = Object.create({}, {
  getFoo: {
    value: function () { return this.foo; }
  } 
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']

如果想获取不可枚举的属性,可以使用getOwnPropertyNames来获取所有属性。而且,在es6中,如果传入的参数不是对象,那么该参数会被强制转换成对象,但是这在es5中会出现类型错误。