用浅/深拷贝、和HTML5方法解决js对象的引用的问题

先来看一个例子

例一:

var a=[1,2,3];
var b=a;
b.push(4);
alert(b);//1,2,3,4
alert(a);//1,2,3,4
var a=[1,2,3];
var b=a;
b=[1,2,3,4]
alert(b);//1,2,3,4
alert(a);//1,2,3

这两种方法得出的结果是不一样的。

第一个程序,是对象的引用, 把a的值附给b,a与b之间是引用的关系,当两者之间是引用的关系时,改变任一变量,都会影响另一个变量。

第二个程序,只是对b的值改变,虽然b=a ,但是当改变b的值时,又重新建立了一个地址,这个地址与a无关,所以在改变b值时,与a无关,这有点类似于C中的指针

再来看一个例子

例二:

var a={
     name:‘hello‘
};
var b=a;
b.name=‘hi‘;
alert(a.name);//当然了,这个结果肯定是hi

如何解决上面的问题呢?

var a={
     name:‘hello‘
};
function copy(){
    var b={};
    for(var attr in a){
        b[attr]=a[attr]
    }
   return b
}
b.name=‘hi‘;
alert(a.name); //这时的结果就是hello了
        

上面的方法叫浅拷贝,利用for in 把a中属性拷贝给b,但是只是拷贝了一个副本,实际上当修改b的值是不会改变a的值的。当然有浅拷贝就有深拷贝。

var a={
     name:‘{value:‘world‘}‘
}
function copy(){
    var b={};
    for(var attr in a){
        b[attr]=a[attr];
    }
   return b
}
b.name.value=‘space‘;
alert(a.name.value); //这时的结果是space

这时候大家或许或纳闷,用了拷贝了怎么结果还是space呢!因为JSON里面又有一个 value:‘world‘ 这个类型是一个对象,你拷贝过来还是对象,还是对象的引用,所以结果就是space,当然了,或许有会说那就再用一次copy就行。由结果再调用一次copy,对了,就是递归的含义,在函数内部调用函数本身。稍微修改一下程序即可

var a={
     name:‘{value:‘world‘}‘
}
function deepCopy(){
     if(typeof a!=‘object‘){
        return a
    }
    var b={};
    for(var attr in a){
        b[attr]=deepCopy(a[attr]);
    }
   return b
}
b.name.value=‘space‘;
alert(a.name.value); //这时的结果就是world

改的地方有两处,1、执行函数内部调用函数本身   b[attr]=deepCopy(a[attr])   2、终止条件typeof a!=‘object‘  就像上面说的,你用浅拷贝拷的是对象,终止条件就是检测类型不是对象的时候,返回a的值。这样就解决了问题。 上面的方法就是深拷贝

例三:

现在了解了浅/深拷贝,想用HTML5方法去解决。在解决之前,我们很有必要去了解HTML5之前如何将字符串转换成js语句,如下:

var str=‘function task(){alert(‘hello‘)}‘
var fn=eval(str);
task(); //hello

HTML5如何把JSON格式的字符串转成JSON对象,用JSON.parse() 如下:

var a=‘{
  ‘name‘:‘hello‘;
};‘
var json=JSON.parse(a);
alert(json.name); //hello

这个name上加了 ‘ ‘  不加‘ ‘ 时不严格的JSON,JSON.parse 方法要求必须是严格的JSON

如何将JSON对象转成JSON格式的字符串呢,用JSON.stringify()  如下:

var a={
   name:‘hello‘
};
var json=JSON.stingify(a);
alert(json); // ‘{‘name‘:‘hello‘}‘
这时的结果就是 ‘{‘name‘:‘hello‘}‘,这时候就明白了为什么要用严格的JSON格式了

那么用HTML5怎么解决问题呢,那就先把JSON转成字符串,再把JSON格式的字符换转成对象,实习上引用的还是a的副本,并没有真正引用a。这就和拷贝中的副本原理是一样的。如下:
var a={
    name:‘hello‘
};
var str=JSON.stringify(a);
var obj=JSON.parse(str);
var b=obj;
b.name=‘hi‘;
alert(a.name);//hello
拓展:

这种方法实际上在8以下是不兼容的,如何兼容呢,就是引用一个json文件:json2.js,如下

<script type=‘text/javascript‘ src=‘json2.js‘></script>
 
时间: 2024-11-06 11:10:52

用浅/深拷贝、和HTML5方法解决js对象的引用的问题的相关文章

让javascript加载速度倍增的方法(解决JS加载速度慢的问题)

通常我们的网站里面会加载一些js代码,统计啊,google广告啊,百度同盟啊,阿里妈妈广告代码啊, 一堆,最后弄得页面加载速度很慢,很慢. 解决办法:换一个js包含的方式,让javascript加载速度倍增. 把通常加载方式: <script src="xxxx.js"></script> 改变成: 代码如下: <script type="text/javascript"> document.write("<scr

js对象的引用

/*var a = [1,2,3]; var b = [1,2,3]; alert( a == b ); //false*/ //基本类型:赋值的时候只是值得复制 /* var a = 5; var b = a; b+=3; alert(b); alert(a);*/ //对象类型:赋值的时候不仅是值的赋值,而且还有地址的传递. /* var a = [1,2,3]; var b = a; //a和b住一起了,都存了[1,2,3] b.push(4); alert(b); alert(a);*/

js对象字面量属性间相互访问的问题 和 这个问题与执行环境的关系

对象字面量属性间无法相互访问的问题: 我曾经在定义一个对象时, 并出于复用性的考虑试图复用某些属性: // test 1 var person = { firstName : "Bill", lastName : "Gates", fullName : firstName + " " + lastName // 这里报错 } alert(person.firstName); alert(person.lastName); alert(person

9、Cocos2dx 3.0游戏开发三查找值小工厂方法模式和对象

重开发人员的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27704153 工厂方法模式 工厂方法是程序设计中一个经典的设计模式.指的是基类中仅仅定义创建对象的接口,将实际的实现推迟到子类中. 在这里.我们将它稍加推广,泛指一切生成并返回一个对象的静态函数. 一个经典的工厂方法如同这样: Sprite* factoryMethod() { Sprite* ret = new Sprite(); //在这里对 r

9、Cocos2dx 3.0游戏开发找小三之工厂方法模式与对象传值

重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27704153 工厂方法模式 工厂方法是程序设计中一个经典的设计模式,指的是基类中只定义创建对象的接口,将实际的实现推迟到子类中. 在这里,我们将它稍加推广,泛指一切生成并返回一个对象的静态函数. 一个经典的工厂方法如同这样: Sprite* factoryMethod() { Sprite* ret = new Sprite(); //在这里对 ret

jQuery对象与js对象转换

前言 jq方法和js的方法属性是不能互相使用的,所以有时候就需要转一下,下面就介绍下方法. js对象转化为jQuery对象 var box=document.getElementById("box"); var $box=$(box); jQuery对象转化为js对象 var box1=$(box)[0]; var box2=$(box).get(0); 示例: <script src="http://libs.baidu.com/jquery/1.11.3/jquer

方法参数(值调用,引用调用)

Java程序设计语言总是采用按值调用.也就是说,方法得到的总是所有参数的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容. double percent = 10; harry.raiseSalary(percent); //方法调用之后,percent的值还是10 然而,方法参数共有两种类型: 1.基本数据类型(数字.布尔值) 2.对象引用 方法得到的是对象引用的拷贝,对象引用及其它的拷贝同时引用同一个对象. public static void swap(Employee x, E

今天和组内一起写代码时碰到了一个关于命名冲突的问题,最后用js命名空间的方法解决的。

//第一步,首先创建一个全局变量,可以放在自己的js方法库中方便以后用,这个就是用来注册命名空间的方法. ns = function(namespace){ var arr = namespace.split('.');  //将传入的字符串如"com.test.lzn"以'.'隔开做成一个数组 var strNamespace = ""; //这个是为了保存每一步循环进去的包名 for(var i=0;i<arr.length;i++) { if(i!=0)

浅谈 js 对象 toJSON 方法

前些天在<浅谈 JSON.stringify 方法>说了他的正确使用姿势,今天来说下 toJSON 方法吧.其实我觉得这货跟 toString 一个道理,他是给 stringify 方法字符串化的时候调用的.看下 MDN 官方文档吧<toJSON behavior>.非常简单,但是要注意的是他和 stringify 方法第二个参数稍微有点不同.因为 stringify 第二个参数是回调函数时,只是对当前 key 对应的值进行修改.而 toJSON 则是对当前对象进行修改.例如: v