浅谈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 Keycode对照表
Oct 24 Javascript
ASP.NET jQuery 实例5 (显示CheckBoxList成员选中的内容)
Jan 13 Javascript
js操作textarea 常用方法总结
Dec 03 Javascript
通用无限极下拉菜单的实现代码
May 31 Javascript
BootStrap fileinput.js文件上传组件实例代码
Feb 20 Javascript
基于react后端渲染模板引擎noox发布使用
Jan 11 Javascript
mpvue中使用flyjs全局拦截的实现代码
Sep 13 Javascript
vue2.0 + ele的循环表单及验证字段方法
Sep 18 Javascript
node.js开发辅助工具nodemon安装与配置详解
Feb 06 Javascript
基于JS+HTML实现弹窗提示是否确认提交功能
Jun 17 Javascript
VUE实时监听元素距离顶部高度的操作
Jul 29 Javascript
javascript局部自定义鼠标右键菜单
Dec 08 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
CI框架中redis缓存相关操作文件示例代码
2016/05/17 PHP
php compact 通过变量创建数组
2016/11/15 PHP
PHP面向对象程序设计组合模式与装饰模式详解
2016/12/02 PHP
php实现查询功能(数据访问)
2017/05/23 PHP
php7连接MySQL实现简易查询程序的方法
2020/10/13 PHP
Prototype Template对象 学习
2009/07/19 Javascript
JavaScript.The.Good.Parts阅读笔记(二)作用域&amp;闭包&amp;减缓全局空间污染
2010/11/16 Javascript
基于jquery实现的一个选择中国大学的弹框 (数据、步骤、代码)
2012/07/26 Javascript
js实现div层缓慢收缩与展开的方法
2015/05/11 Javascript
CSS+JS实现点击文字弹出定时自动关闭DIV层菜单的方法
2015/05/12 Javascript
JavaScript中Number.MAX_VALUE属性的使用方法
2015/06/04 Javascript
CSS或者JS实现鼠标悬停显示另一元素
2016/01/22 Javascript
HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
2016/01/26 Javascript
全国省市二级联动下拉菜单 js版
2016/05/10 Javascript
AngularJS模板加载用法详解
2016/11/04 Javascript
vue项目中做编辑功能传递数据时遇到问题的解决方法
2016/12/19 Javascript
vue使用v-if v-show页面闪烁,div闪现的解决方法
2018/10/12 Javascript
clipboard在vue中的使用的方法示例
2018/10/19 Javascript
webpack + vue 打包生成公共配置文件(域名) 方便动态修改
2019/08/29 Javascript
Element 默认勾选表格 toggleRowSelection的实现
2019/09/04 Javascript
[44:37]完美世界DOTA2联赛PWL S3 Forest vs access 第一场 12.11
2020/12/13 DOTA
Python计时相关操作详解【time,datetime】
2017/05/26 Python
python编写Logistic逻辑回归
2020/12/30 Python
Python自动化之数据驱动让你的脚本简洁10倍【推荐】
2019/06/04 Python
简单了解python单例模式的几种写法
2019/07/01 Python
Django 创建新App及其常用命令的实现方法
2019/08/04 Python
python实现根据给定坐标点生成多边形mask的例子
2020/02/18 Python
Python实现像awk一样分割字符串
2020/09/15 Python
Opencv python 图片生成视频的方法示例
2020/11/18 Python
Python爬虫实例之2021猫眼票房字体加密反爬策略(粗略版)
2021/02/22 Python
CSS3 实用技巧:实现黑白图像效果示例代码
2013/07/11 HTML / CSS
一波HTML5 Canvas基础绘图实例代码集合
2016/02/28 HTML / CSS
html5中使用hotcss.js实现手机端自适配的方法
2020/04/23 HTML / CSS
世界上最大的乐器零售商:Guitar Center
2017/11/07 全球购物
Farfetch巴西官网:奢侈品牌时尚购物平台
2020/10/19 全球购物
编写一个类体现构造,公有,私有方法,静态,私有变量
2013/08/10 面试题