浅谈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 相关文章推荐
jQuery中:gt选择器用法实例
Dec 29 Javascript
javascript给span标签赋值的方法
Nov 26 Javascript
JavaScript中数组slice和splice的对比小结
Sep 22 Javascript
js实现图片360度旋转
Jan 22 Javascript
javascript基本数据类型和转换
Mar 17 Javascript
vue+element实现批量删除功能的示例
Feb 28 Javascript
vue.js 实现输入框动态添加功能
Jun 25 Javascript
使用mixins实现elementUI表单全局验证的解决方法
Apr 02 Javascript
Js参数RSA加密传输之jsencrypt.js的使用
Feb 07 Javascript
js实现星星打分效果
Jul 05 Javascript
JavaScript本地储存:localStorage、sessionStorage、cookie的使用
Oct 13 Javascript
javascript实现京东快递单号的查询效果
Nov 30 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创建桌面快捷方式的实例代码
2014/02/17 PHP
yii2.0之GridView自定义按钮和链接用法
2014/12/15 PHP
PHP查询并删除数据库多列重复数据的方法(利用数组函数实现)
2016/02/23 PHP
Jquery 类网页微信二维码图块滚动效果具体实现
2013/10/14 Javascript
jQuery 计算iframe 窗口大小的方法
2014/05/13 Javascript
NODE.JS加密模块CRYPTO常用方法介绍
2014/06/05 Javascript
深入理解JavaScript系列(39):设计模式之适配器模式详解
2015/03/04 Javascript
javascript与jquery中的this关键字用法实例分析
2015/12/24 Javascript
js字符串截取函数slice、substring和substr的比较
2016/05/17 Javascript
JS中静态页面实现微信分享功能
2017/02/06 Javascript
React-Native做一个文本输入框组件的实现代码
2017/08/10 Javascript
让网站自动生成章节目录索引的多个js代码
2018/01/07 Javascript
在JS循环中使用async/await的方法
2018/10/12 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
2018/11/07 Javascript
vue 项目 iOS WKWebView 加载
2019/04/17 Javascript
手把手教您实现react异步加载高阶组件
2020/04/07 Javascript
vue-preview动态获取图片宽高并增加旋转功能的实现
2020/07/29 Javascript
three.js着色器材质的内置变量示例详解
2020/08/16 Javascript
Hadoop中的Python框架的使用指南
2015/04/22 Python
Python文件读取的3种方法及路径转义
2015/06/21 Python
Python编程中对super函数的正确理解和用法解析
2016/07/02 Python
使用Python多线程爬虫爬取电影天堂资源
2016/09/23 Python
Python判断某个用户对某个文件的权限
2016/10/13 Python
Python 常用的安装Module方式汇总
2017/05/06 Python
python绘制地震散点图
2019/06/18 Python
Python面向对象程序设计之类和对象、实例变量、类变量用法分析
2020/03/23 Python
linux面试相关问题
2012/08/11 面试题
HttpServlet类中的主要方法都有哪些?各自的作用是什么?
2014/03/16 面试题
优秀导游先进事迹材料
2014/01/25 职场文书
初一体育教学反思
2014/01/29 职场文书
银行委托书范本
2014/04/04 职场文书
中学生评语大全
2014/04/18 职场文书
党员政治学习材料
2014/05/14 职场文书
优秀员工演讲稿
2014/05/19 职场文书
2015年暑期实践报告范文
2015/07/13 职场文书
CAD实训总结范文
2015/08/03 职场文书