浅谈js中的引用和复制(传值和传址)


Posted in Javascript onSeptember 18, 2016

好像一般很少人讲到js中的引用和复制,不过弄清楚这个概念可以帮助理解很多东西

先讲一下很基础的东西,看看js中几种数据类型分别传的什么

引用:对象、数组、函数

复制:数字、布尔

字符串单独说明,因为它的特殊性,无法确定是传递引用还是复制数值(因为字符串的值是没法改变的,所以纠结这个问题也是没意义的)但是用于比较的时候显然是属于传值比较(稍后具体说比较的事)

下面讲一下在使用中的具体体现

最普通的使用就是赋值了

var a = 1;
var b = a;  //赋的是a的复制值
b ++;
alert(a);  //"1"  b的修改不影响a
/****************************************/
var a = [1];
var b = a;   //赋的是a的引用 
b[0] ++;
alert(a); //"2"  b的修改对a也有效  不过当然b = [2];这种修改对a是没用的。

函数的参数

传值的传递:传给函数的是数值的一个复制,函数中对其的修改外部不可见

var a = 1;
var b = 2;
function change(a,b) {
 var c = a;
 a = b;   //用新引用覆盖
 b = c;
 alert(a);  //"2"     
 alert(b);  //"1"
}
change(a,b);
alert(a);  //"1"     
alert(b);  //"2"

传址的传递:传给函数的是数值的一个引用,函数中对其属性的修改外部可见,但用新引用覆盖其则在外部不可见,比如

var a = [1, 2, 3];
var b = [5, 6];
function change(a,b) {
 a[0] = 4;  //对其属性的修改外部可见 
 var c = a;
 a = b;   //用新引用覆盖
 b = c;
 alert(a);  //"5,6"     
 alert(b);  //"4,2,3"
}
change(a,b);
alert(a);  //"4,2,3"
alert(b);   //"5,6"

从结果可以看出a和b并没有互换   因为用新引用覆盖在外部不可见 这个很自然 因为函数只是拿到了引用 并没有权力更改引用

下面这个就不同了

var a = [1, 2, 3];
var b = [5, 6];
function change() {
 var c = a;
 a[0] = 4;
 a = b;
 b = c;
};
change();
alert(a);  //"5,6"
alert(b);  //"4,2,3"

这里成功实现互换 

又得提到js的块级作用域了,这个放某些语言里定然是要报未定义错误的,因为js没有块级作用域,所以它在change里找不到变量a,b就会自觉的到上层去找,所以这里的a,b是全局变量的引用

而上面的那个a,b则是change函数中的变量,在调用函数时传递了a,b的引用赋给了这两个变量,但是并不能改变全局中的a,b,这里换个名字大概就好理解多了

这个稍微提下    有些走题了。。。。

回到引用和复制 在比较运算中的注意事项

传值的比较比较的是数值 而传址的比较比较的是引用,引用不同即使数值相同也不等

1 == 1;  //true
1 === 1;  //true
[0] == [0]; //false
[0][0] == [0][0];  //true
[0][0] === [0][0];  //true
[0].toString() == [0].toString();  //true

闭包中。。。。

闭包大概是js中最纠结的东西 我们部门面试的经典试题,常考不衰啊。。。。

这里我先不说闭包的东西,只说一下涉及传值和引用的部分,等我哪天确定自己可以用清晰的条例、简明的语言、生动的实例彻底的说清楚那个东西,再详细介绍这个提js不能不提的家伙。。。

闭包中,内部函数用外部函数的局部变量使用引用的方式而不是复制

其实这也是理解闭包的一个很重要的部分 可以用这个解释一个很经典的闭包现象,很多地方在说明闭包的时候都会用到的一个例子

/*构造一个函数,给数组中的节点设置事件处理程序,当点击一个节点时,alert出节点的序号*/
var add_handlers = function (nodes) {
  var i;
  for (i = 0, l = nodes.length; i < l; i ++) {
    nodes[i].onclick = function (e) {
      alert(i);  // 当然这里的结果必然是每次alert的都是节点总数。。。。
    }
  }
};

为什么每次alert的都是节点总数 而不是预期的序号呢,这个如果用复制和引用解释就相当容易了

因为内部函数在使用外部变量时使用引用的方式而不是复制,就是说我给每个节点设置onclick事件的时候将i的引用传递给了alert,当我点击节点触发onclick事件的时候,i的值已经变成了节点总数。。。

var add_handlers = function (nodes) {
  var i;
  for (i = 0, l = nodes.length; i < l; i ++) {
 
    nodes[i].onclick = function (i) {
      return function(){
      alert(i);  
      }
 }(i);
  }
};

这样修改后之所以正确是因为此时传进去的是i的值的复制,其实和普通函数是一样的,不要因为加了闭包就迷糊了,回归本源去思考就明白了,本源就是上面讲到的传址的传递

顺便提一句,不要被闭包这个古怪的名字唬住了,其实它和我们平时用的函数原理是一样的,抛开那些“更长的生命周期”“保护私有变量”等闭包所谓的特性,把它当成一个普通的函数(也可以换个角度把全局函数看成一个特殊的闭包),很容易就可以理解了

关键是要放下所有的浮华,回归最本质。。。又跑题了。。。

以上这篇浅谈js中的引用和复制(传值和传址)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript为对象原型prototype添加属性的两种方式
Aug 01 Javascript
Node.js实战 建立简单的Web服务器
Mar 08 Javascript
jQuery选择器源码解读(一):Sizzle方法
Mar 31 Javascript
简介JavaScript中setUTCSeconds()方法的使用
Jun 12 Javascript
深入理解事件冒泡(Bubble)和事件捕捉(capture)
May 28 Javascript
推荐三款不错的图片压缩上传插件(webuploader、localResizeIMG4、LUploader)
Apr 21 Javascript
gulp解决跨域的配置文件问题
Jun 08 Javascript
jquery.onoff实现简单的开关按钮功能(推荐)
May 24 jQuery
vue+axios+promise实际开发用法详解
Oct 15 Javascript
详解在Angular4中使用ng2-baidu-map的方法
Jun 19 Javascript
微信小程序实现打开并下载服务器上面的pdf文件到手机
Sep 20 Javascript
JavaScript实现简单的弹窗效果
May 19 Javascript
jQuery实现鼠标经过时高亮,同时其他同级元素变暗的效果
Sep 18 #Javascript
JavaScript每天必学之事件
Sep 18 #Javascript
jQuery实现简单的网页换肤效果示例
Sep 18 #Javascript
js完整倒计时代码分享
Sep 18 #Javascript
Javascript中常见的逻辑题和解决方法
Sep 17 #Javascript
js手动播放图片实现图片轮播效果
Sep 17 #Javascript
Bootstrap时间选择器datetimepicker和daterangepicker使用实例解析
Sep 17 #Javascript
You might like
PHP出错界面
2006/10/09 PHP
浅析memcache启动以及telnet命令详解
2013/06/28 PHP
PHP callback函数使用方法和注意事项
2015/01/23 PHP
php生成HTML文件的类方法
2019/10/11 PHP
syntaxhighlighter 使用方法
2007/07/02 Javascript
jquery validate使用攻略 第四步
2010/07/01 Javascript
js 完美图片新闻轮转效果,腾讯大粤网首页图片轮转改造而来
2011/11/21 Javascript
不使用XMLHttpRequest实现异步加载 Iframe和script
2012/10/29 Javascript
javascript 星级评分效果(手写)
2012/12/24 Javascript
js购物车实现思路及代码(个人感觉不错)
2013/12/23 Javascript
jQuery实现首页顶部可伸缩广告特效代码
2015/04/15 Javascript
javascript实现将文件保存到本地方法汇总
2015/07/26 Javascript
js 获取经纬度的实现方法
2016/06/20 Javascript
jQuery实现删除li节点的方法
2016/12/06 Javascript
xmlplus组件设计系列之网格(DataGrid)(10)
2017/05/05 Javascript
Node.js使用orm2进行update操作时关联字段无法修改的解决方法
2017/06/13 Javascript
JS库中的Particles.js在vue上的运用案例分析
2017/09/13 Javascript
使用 Node.js 模拟滑动拼图验证码操作的示例代码
2017/11/02 Javascript
简单谈谈javascript高级特性
2019/09/04 Javascript
javascript浅层克隆、深度克隆对比及实例解析
2020/02/09 Javascript
原生JS与JQ获取元素的区别详解
2020/02/13 Javascript
OpenCV2.3.1+Python2.7.3+Numpy等的配置解析
2018/01/05 Python
简单实现python画圆功能
2018/01/25 Python
分享Python切分字符串的一个不错方法
2018/12/14 Python
Python使用Beautiful Soup爬取豆瓣音乐排行榜过程解析
2019/08/15 Python
Python 等分切分数据及规则命名的实例代码
2019/08/16 Python
windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码
2020/05/07 Python
django 解决扩展自带User表遇到的问题
2020/05/14 Python
html5 利用canvas手写签名并保存的实现方法
2018/07/12 HTML / CSS
全球领先的美容用品专卖店:Beauty Plus Salon
2018/09/04 全球购物
欧克利英国官网:Oakley英国
2019/08/24 全球购物
英国电子专家:maplin
2019/09/04 全球购物
母亲节感恩活动记录
2014/03/16 职场文书
2014年绩效考核工作总结
2014/12/11 职场文书
Windows 11上手初体验:任务栏和开始菜单等迎来大改
2021/11/21 数码科技
《勇者辞职不干了》ED主题曲无字幕动画MV公开
2022/04/13 日漫