JavaScript对象复制(一)(转载)
在JavaScript很多人复制一个对象的时候都是直接用"=",因为大家都觉得脚本语言是没有指针、引用、地址之类的,所以直接用"="就可以把一个对象复制给另外一个对象,如下代码:
var i1 = 1;
var i2 = i1;
i2 = 2;
alert("i1:"+i1+",i2:"+i2);
输出结果:i1:1 , i2:2
但可能没有发现,这种“复制”用在对象(object)类型是“错误”的,因为这只是把对象的地址复制,所以如下代码会进行了一次“错误”的复制:
代码2

var o1 = {i : 1,s : "o1"};
var o2 = o1;
o2.i=2;
o2.s="o2";
alert("o1.i:"+o1.i+",o2.i:"+o2.i);
alert("o1.s:"+o1.s+",o2.s:"+o2.s);

输出:o1.i:2 , o2.i:2
o1.s:o2 , o2.s:o2
可能你会问为什么 代码1 可以复制,但 代码2 却没有复制?
其实准确来说是“基本数据类型”可以复制,非基本类型(包括字符串)只复制其引用。为什么要这样做呢?原因很简单,为了减少开销。大家都知道非基本类型有时候很大,如果重新开辟内存来存放一个这么大的对象,开销很大,导致运行会很慢。脚本语言是直接在虚拟机(或者浏览器)运行,它经过虚拟机这一层来处理代码,速度已经相对其他编译语言慢很多,所以如果把非基本对象再做“复制”,那么可能你要等上一年半载才能运行得了程序,因此只能复制对象的引用。
但很多时候我们并不希望函数去修改我们的这些对象参数,这就需要使用到对象的克隆,我们应该对该对象做一个克隆,然后操作这个克隆的对象,这样就不会影响我们的原对象了。 如果需要把整个对象复制,必须一个一个属性或方法引用复制一偏,这样为每个属性开辟内存来存放你需要的数据,当然这样相对来说会很慢,尤其数据量很多的时候, 在js中并没有对象克隆功能,因此需要我们自己实现,实现方法也不复杂,基本上是做一些属性复制,我在网上找了一些,但有些实现并不好,如对于array对象克隆后就成json对象了,并没有保留原来的数组方式。不过最后还是找到了一个很好的克隆函数,完美实现了js对象的克隆功能,不论是Array对象或者是普通的Object,都可以很好的进行克隆,这个函数使用constructor(函数构造器)进行复制。
方法一:

Object.prototype.Clone = function(){
var objClone;
if (this.constructor == Object){
objClone = new this.constructor();
}else{
objClone = new this.constructor(this.valueOf());
}
for(var key in this){
if ( objClone[key] != this[key] ){
if ( typeof(this[key]) == 'object' ){
objClone[key] = this[key].Clone();
}else{
objClone[key] = this[key];
}
}
}
objClone.toString = this.toString;
objClone.valueOf = this.valueOf;
return objClone;
}

方法二:

function clone(obj){
var o;
switch(typeof obj){
case 'undefined': break;
case 'string' : o = obj + '';break;
case 'number' : o = obj - 0;break;
case 'boolean' : o = obj;break;
case 'object' :
if(obj === null){
o = null;
}else{
if(obj instanceof Array){
o = [];
for(var i = 0, len = obj.length; i < len; i++){
o.push(clone(obj[i]));
}
}else{
o = {};
for(var k in obj){
o[k] = clone(obj[k]);
}
}
}
break;
default:
o = obj;break;
}
return o;
}

方法三:

function clone3(obj){
function Clone(){}
Clone.prototype = obj;
var o = new Clone();
for(var a in o){
if(typeof o[a] == "object") {
o[a] = clone3(o[a]);
}
}
return o;
}

方法四:
arrayObj=[1,2,3,4,5]; arrayObj.slice(0); //返回数组的拷贝数组,注意是一个新的数组,不是指向 arrayObj.concat(); //返回数组的拷贝数组,注意是一个新的数组,不是指向
JavaScript对象复制(一)(转载)的更多相关文章
- JavaScript对象复制
近期项目因为怕数据污染所以用到了js的对象复制 js里的对象都是继承自object,是引用类型,所以无法通过=号复制 所以整理了一些常用的复制方法,如下 一.通过JSON序列化和反序列化创建新的对象 ...
- Javascript 对象复制
如果对象只是一个数据集,可采用json化再反json化的方式克隆一个对象,这个过程会丢失对象的方法.效率比较低. 可以采用如下递归的方式复制一个对象. function clone(target) { ...
- Javascript 对象复制(深浅拷贝)
一.数据类型分类: 基本变量 引用类型 二.什么叫做指针指向 栈内存.堆内存.指针指向(如下红圈圈的斜线). 三.赋值.拷贝.引用区别? 赋值指一个变量赋予某个值,包含两种方式,一种是直接量,另一种, ...
- JavaScript对象复制(二)
<script> function copy(a) { ret = {}; for (sth in a) { temp = a[sth]; if (temp instanceof Arra ...
- JavaScript对象的深浅复制
前言 从层次上来看,对象的复制可以简单地分为浅复制和深复制,顾名思义,浅复制是指只复制一层对象的属性,不会复制对象中的对象的属性,对象的深复制会复制对象中层层嵌套的对象的属性. 在复制对象时,除了要复 ...
- 【转】JavaScript中的对象复制(Object Clone)
JavaScript中并没有直接提供对象复制(Object Clone)的方法.因此下面的代码中改变对象b的时候,也就改变了对象a. a = {k1:1, k2:2, k3:3}; b = a; b. ...
- 转载 -- 如何判断Javascript对象是否存在
http://www.ruanyifeng.com/blog/2011/05/how_to_judge_the_existence_of_a_global_object_in_javascript.h ...
- 如何深度复制一个javascript对象
前言 最近有人问我,如何将一个对象复制一份,因为他遇到了一个需求,需要将后端获取的数据,保存一份,原始数据会因为交互而发生变化,最终需要对比两份数据的异同. 他是一个刚入行的小朋友,他的实现方式就是新 ...
- javaScript系列 [02]-javaScript对象探析
[02]-javaScript对象探析 题记:多年前,以非常偶然的方式关注了微信公众号“面向对象”,本以为这个公众号主要以分享面向对象编程的干货为主,不料其乃实实在在的猿圈相亲平台.通过查看公开资料, ...
随机推荐
- Java8的flatMap如何处理有异常的函数
Java8的flatMap函数,作用是:如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional. 见到的映射函数往往都只有一句话,连大括号都不需要加的,如下: ...
- 自学Aruba3.2-Aruba配置架构-Virtual AP配置要点
点击返回:自学Aruba之路 自学Aruba3.2-Aruba配置架构-Virtual AP配置要点 1. AP.AP-Group和Virtual-AP的关系 解析列举: AP1.AP3, ...
- NOI 笔试题库(我背不住的部分)
吐槽 为什么C++选手要会编译Pascall啊!为什么Emacs选手要会使用Vim啊! Linux 中为文件改名使用的命令是:mv 在Linux 中删除当前目录下的test 目录的命令是:rm -r ...
- BZOJ 4004 [JLOI2015]装备购买 | 线性基
题目链接 Luogu P3265 题解 非常正常的线性基! 但是我不会线性基-- (吐槽:#define double long double 才过--) #include <cstdio> ...
- [poj3278]抓住那头牛
题目描述 Farmer John has been informed of the location of a fugitive cow and wants to catch her immediat ...
- 安装 Minio服务
#MINIO SERVER Minio是在Apache License v2.0下发布的对象存储服务器.它与Amazon S3云存储服务兼容. 它最适合存储非结构化数据,如照片,视频,日志文件,备份和 ...
- cf500E New Year Domino (倍增)
先用线段树处理出推倒某一个后能覆盖到的最右端的位置R(绝对不能是最右边的那个骨牌,因为有可能右面的很短,左面的巨长(R不随L单调),后面算花费又需要用到这个位置),之后可以花费R到第一个比R大的左端点 ...
- Linux下的定时器类实现(select定时+线程)
更好的计时器类实现:LINUX RTC机制实现计时器类(原创) 很多时候需要在LINUX下用到定时器,但像setitimer()和alarm()这样的定时器有时会和sleep()函数发生冲突,这样就给 ...
- vue使用v-if v-show页面闪烁,div闪现的解决方法
v-if和v-show可能是日常开发中最常用的两个指令,虽然看上去两者功能是类似的,但是两者还是存在很大区别的. v-if与v-show区别: 在切换 v-if 块时,Vue.js 有一个局部编译/卸 ...
- 走进JVM之一 自己编译openjdk源码
想要深入了解JVM,就必须了解其实现机制.了解JVM实现的最好方法便是自己动手编译JDK.好了,让我们开始吧! 1. 准备工作 获取OpenJDK源码 本次编译选择的是OpenJDK7u,官方源码包 ...