javascript中参数的内存引用关系及解决方案

广告位招租
扫码页面底部二维码联系

JavaScript和很多其他编程语言一著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】样,变量在内存中一旦生成,往往会通过引用本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】来反复使用这个变量的值,也就是我们常说的【本文首发于唐霜的博客】【本文受版权保护】引用传递。但是有的时候,我们希望一个新的【版权所有】唐霜 www.tangshuang.net【本文受版权保护】变量,拥有原始变量的所有成员,同时又有自【作者:唐霜】【版权所有】唐霜 www.tangshuang.net己的新成员,在类的继承里面这个很好做到,【版权所有,侵权必究】原创内容,盗版必究。但是对于变量,却没有现成的办法,因为继承未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net一个变量意味着要声明一个新变量,在内存空【未经授权禁止转载】【未经授权禁止转载】间中开辟一块新的区域,把原始变量的整个内本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】存结构拷贝过来。但是我们知道,变量中的某转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。个成员,往往又是另外一个变量(匿名)的引本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。用,所以克隆起来又增加了难度。我们下面来【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。看一个案例:

【转载请注明来源】【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】et 获取更多精彩内容】【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。
function Test(options) {
  this.options = options;
}
var opt = {
  name : 'kandi',
  age : 12
};
var a = new Test(opt);

var opt2 = opt;
opt2.name = 'candy';
var b = new Test(opt2);

console.log('a:' + a.options.name + ';b:' + b.options.name);

我们会发现,console显示的两个na转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。me都是candy,其实我们希望a.options.nam【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。e为kandi。

【作者:唐霜】【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】et 获取更多精彩内容】【版权所有,侵权必究】未经授权,禁止复制转载。

这里就涉及到了变量的内存引用问题。当声明转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。opt2=opt的时候,其实是将opt所【转载请注明来源】【本文首发于唐霜的博客】指向的内存地址赋值给opt2,也就是说,【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】opt2和opt虽然名称不同,但实际内容【作者:唐霜】【版权所有】唐霜 www.tangshuang.net是一样的,相当于一个房子挂了两张门牌。当【本文受版权保护】【版权所有】唐霜 www.tangshuang.netopt2.name修改之后,实际上是修改著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】了opt2对应的内存区域里的name,而【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。opt和opt2拥有同一块内存区域,op【未经授权禁止转载】【原创不易,请尊重版权】t.name自然也就变为了candy.

著作权归作者所有,禁止商业用途转载。【转载请注明来源】

这种情况和下面的情况完全是两回事:

【作者:唐霜】【原创不易,请尊重版权】未经授权,禁止复制转载。
var a = 'my name';
var b = a;
b = 'your name';

console.log(a + ' vs. ' + b);

这段代码并不涉及引用传递的问题。

【未经授权禁止转载】原创内容,盗版必究。转载请注明出处:www.tangshua【本文受版权保护】【本文受版权保护】ng.net本文版权归作者所有,未经授权不得转载。

回到前面,当opt2.name改变之后,本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。a.options.name会首先去到实【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。例化的Test类中找出a.options【原创内容,转载请注明出处】【未经授权禁止转载】,由于a.options是对传入参数的引【作者:唐霜】【原创内容,转载请注明出处】用,所以当使用a.options.nam未经授权,禁止复制转载。原创内容,盗版必究。e的时候,实际上是找到opt.name。未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】opt2.name值的改变意味着意味着对未经授权,禁止复制转载。【转载请注明来源】应内存空间里name值的改变,所以即使n【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】ew了两次Test类,但是当option本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。s值变化的时候,a、b对应的内存空间中的【原创内容,转载请注明出处】【转载请注明来源】引用并没有改变,而是内存中name的值变【版权所有,侵权必究】【本文首发于唐霜的博客】了。

著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netng.net【版权所有】唐霜 www.tangshu【转载请注明来源】未经授权,禁止复制转载。ang.net

new Test并不会将实参也固定到ne转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.netw的内存空间中,也就是说并非克隆参数变量转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】,而是仅仅引用了实参的内存地址。new 【版权所有,侵权必究】转载请注明出处:www.tangshuang.netTest的时候新开辟的内存空间,仅限于T【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。est实例化对象,每一个实例化对象的内存本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】空间是独享的,但是它们中引用的其他内存空本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。间,却与自身的内存空间实际上没有多大的关原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。系。

【作者:唐霜】【原创不易,请尊重版权】

那么怎么来解决上面的问题呢?通过深拷贝o本文版权归作者所有,未经授权不得转载。【转载请注明来源】pt到opt2,创建一个和opt对应的内【未经授权禁止转载】本文作者:唐霜,转载请注明出处。存内容完全相同的另一块内存内容,并赋值给【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】opt2。我们可以使用jquery的ex【原创不易,请尊重版权】【未经授权禁止转载】tend方法来实现深拷贝,如下:

【版权所有,侵权必究】转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.netng.net【原创内容,转载请注明出处】
var opt = {
  name : 'kandi',
  age : 12
};
var opt2 = $.extend({},opt,{name : 'candy'});

这样opt2就会开辟新的内存空间,并拥有著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】属于自己的完整的继承于opt的各个成员。

【原创内容,转载请注明出处】转载请注明出处:www.tangshua【本文首发于唐霜的博客】【作者:唐霜】ng.net【版权所有】唐霜 www.tangshu【本文受版权保护】著作权归作者所有,禁止商业用途转载。ang.net【原创不易,请尊重版权】

2016-06-23 4080

为价值买单,打赏一杯咖啡

本文价值40.8RMB
已有1条评论
  1. […] 引用数据类型,不单单是为了解决复杂的变量(上下文)数据结构存储,引用传递可以帮助我们完成很多复杂的数据操作。本文特别要介绍的,是跨作用域改变堆内存中的值。为了形象的了解这个情况,你可以先阅读一下《javascript中参数的内存引用关系及解决方案》这篇文章中我给出的一种情况。 […]