js中对Object对象的一些常用操作总结

35481次浏览

前言

我前面的文章,写过js中“类”与继承的一些文章。ES5我们可以通过 构造函数 或者 Object.create()等方式来模拟出js中的“类”,当然,对象呢是类的实例化,我们可以通过如下方式创建对象:

var haorooms ={};
或者
var haorooms = new Object()

今天主要总结一下Object的一些常用方法。

Object.assign()

1、可以用作对象的复制

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

2、可以用作对象的合并

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 }, 注意目标对象自身也会改变。

上面我们看到,目标对象o1自身也发生了改变。假如我们不想让o1改变,我们可以把三个对象合并到一个空的对象中,操作如下:

 var obj = Object.assign({},o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1 }

注意:以下几个地方可能copy或者合并不成功,经常在面试中出现!

1、继承属性和不可枚举属性是不能拷贝的

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 }

2、原始类型会被包装为 object

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" }

3、异常会打断接下来的拷贝任务

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()

这个我之前就提到过了,可以模拟出js中的“类”。具体可以看:http://www.haorooms.com/post/js_lei_jicheng

注意!上文中我只应用了Object.create()的第一个参数,其实还有第二个参数!

Object.create(proto, [ propertiesObject ])

第二个参数是可选的,主要用于指定我们创建的对象的一些属性,(例如:是否可读、是否可写,是否可以枚举等等)可以通过下面案例来了解第二个参数!

var o;
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) }
}})

// 创建一个以另一个空对象为原型,且拥有一个属性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.is()

用来判断两个值是否是同一个值。

下面是一些例子,面试中可能会提及

Object.is('haorooms', 'haorooms');     // true
Object.is(window, window);   // true

Object.is('foo', 'bar');     // false
Object.is([], []);           // false

var test = { a: 1 };
Object.is(test, test);       // true

Object.is(null, null);       // true

// 特例
Object.is(0, -0);            // false
Object.is(-0, -0);           // true
Object.is(NaN, 0/0);         // true

Object.keys()

这个方法会返回一个由给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)。

例如:

/* 类数组对象 */ 
var obj = { 0 : "a", 1 : "b", 2 : "c"};
alert(Object.keys(obj)); 
// 弹出"0,1,2"

/* 具有随机键排序的数组类对象 */
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(an_obj)); 
// console: ['2', '7', '100']

常用其他操作

1、删除对象中的某个值,前面案例中也谢了可以直接用delete

delete o.p

2、对象循环,这个我之前单独写了一篇文章:http://www.haorooms.com/post/object_bjxh

3、对象或者数组赋值

js中对象和数组赋值,不和PHP等后端语言一样,只能赋值一层,例如:

var haorooms={};
//可以这么写

haorooms["前端博客"]="Haorooms,Aaron个人博客。记录本人工作中遇到的问题,以及经验总结和分享!";

//但是假如如下写就会报错!
haorooms["前端博客"]["des"]="Haorooms,Aaron个人博客。记录本人工作中遇到的问题,以及经验总结和分享!"

//Uncaught TypeError: Cannot set property 'des' of undefined

我们在循环多层赋值的时候可以这么写:

var haorooms={};

haorooms["前端博客"] = haorooms["前端博客"] || {};

haorooms["前端博客"]["des"]=haorooms["前端博客"]["des"] || "Haorooms,Aaron个人博客。记录本人工作中遇到的问题,以及经验总结和分享"

这样就可以多层赋值了!此方法同样可以应用在数组上面!

其他一些不是很常用的对象操作属性。如下:

1、Object.freeze() 方法可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。

2、Object.isFrozen() 方法判断一个对象是否被冻结(frozen)。

3、Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

4、Object.isSealed() 方法判断一个对象是否是密封的(sealed)。

5、Object.seal() 方法可以让一个对象密封,并返回被密封后的对象。密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象。

Tags: jsobject

相关文章: