js对象实例详解(JavaScript对象深度剖析,深度理解(3)

而克隆对象的时候就要分两种情况了,简单的赋值会让两个变量指向同一块内存,两者代表同一个对象,甚至算不上克隆克隆。但我们常常需要的是两个属性和方法完全相同但却完全独立的对象,称为深度克隆。我们接下来讨论几种深度克隆的方法。

说几句题外的话,业界有一个非常知名的库 immutable ,个人认为很大程度上解决了深度克隆的痛点,我们修改一个对象的时候,很多时候希望得到一个全新的对象(比如Redux每次都要用一个全新的对象修改状态),由此我们就需要进行深度克隆。而 immutable 相当于产生了一种新的对象类型,每一次修改属性都会返回一个全新的 immutable 对象,免去了我们深度克隆的工作是小事,关键性能特别好。

历遍属性

function clone(obj){ var newobj = obj.constructor === Array ? [] : {}; // 用 instanceof 判断也可 if(typeof obj !== 'object' || obj === null ){ return obj } else { for(var i in obj){ newobj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i]; // 只考虑 对象和数组, 函数虽然也是引用类型,但直接赋值并不会产生什么副作用,所以函数类型无需深度克隆。 } } return newobj; };

原型式克隆

function clone(obj){ function F() {}; F.prototype = obj; var f = new F(); for(var key in obj) { if(typeof obj[key] =="object") { f[key] = clone(obj[key]) } } return f ; }

这种方式不能算严格意义上的深度克隆,并没有切断新对象与被克隆对象的联系,被克隆对象作为新对象的原型存在,虽然新对象的改变不会影响旧对象,但反之则不然!而且给新对象属性重新赋值的时候只是覆盖了原型中的属性,在历遍新对象的时候也会出现问题。这种方式问题重重,除了实现特殊目的可以酌情使用,通常情况应避免使用。
json序列化

var newObj = JSON.parse(JSON.stringify(obj));

这是我最喜欢的方式了!简短粗暴直接!但是最大的问题是,毕竟JSON只是一种数据格式所以这种方式只能克隆属性,不能克隆方法,方法在序列化以后就消失了。。。

一些Object的方法与需要注意的点

Object 自身的方法:

设置属性,Object.defineProperty(obj, prop, descriptor) 根据 descriptor 定义 obj 的 prop 属性(值,是否可写可枚举可删除等)。

Object.getOwnPropertyDescriptor(obj, prop) 返回 obj 的 prop 属性的描述。

使对象不可拓展,Object.preventExtensions(obj),obj 将不能添加新的属性。

判断对像是否可拓展,Object.isExtensible(obj)。

密封一个对象,Object.seal(obj),obj 将不可拓展且不能删除已有属性。

判断对象是否密封,Object.isSealed(obj)。

冻结对象,Object.freeze(obj) obj 将被密封且不可修改。

判断对象是否冻结,Object.isFrozen(obj)。

获取对象自身属性(包括不可枚举的),Object.getOwnPropertyNames(obj),返回 obj 所有自身属性组成的数组。

获取对象自身属性(不包括不可枚举的),Object.keys(obj),返回 obj 所有自身可枚举属性组成的数组。

当使用for in循环遍历对象的属性时,原型链上的所有可枚举属性都将被访问。

只关心对象本身时用Object.keys(obj)代替 for in,避免历遍原型链上的属性。

获取某对象的原型对象,Object.getPrototypeOf(object),返回 object 的原型对象。

设置某对象的原型对象,Object.setPrototypeOf(obj, prototype),ES6 新方法,设置 obj 的原型对象为 prototype ,该语句比较耗时。

Object.prototype 上的方法:

检查对象上某个属性是否存在时(存在于本身而不是原型链中),obj.hasOwnProperty() 是唯一可用的方法,他不会向上查找原型链,只在 obj 自身查找,返回布尔值。

检测某对象是否存在于参数对象的原型链中,obj.isPrototypeOf(obj2),obj 是否在 obj2 的原型链中,返回布尔值。

检测某属性是否是对象自身的可枚举属性,obj.propertyIsEnumerable(prop),返回布尔值。

对象类型,obj.toString(),返回 "[object type]" type 可以是 Date,Array,Math 等对象类型。

obj.valueOf(),修改对象返回值时的行为,使用如下:

function myNumberType(n) { this.number = n; } myNumberType.prototype.valueOf = function() { return this.number; }; myObj = new myNumberType(4); myObj + 3; // 7

ES6新增特性

判断两个值是否完全相等,Object.is(value1, value2),类似于 === 但是可以用来判断 NaN。

属性和方法简写:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyzfgs.html