JS中函数参数值传递和引用传递
也许大家对于函数的参数都不会太在意,简单来说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。深入研究,你会发现其实没那么简单,这个传参是要分俩种情况(其实这是个错误的说法,ECMAScript中所有函数的参数都是按值传递的——《高程3》原话,之所以这里说俩种,是因为结合引用传参更容易理解)—— 值传参和引用传参。
值传参针对基本类型,引用传参针对引用类型,传参可以理解为复制变量值。基本类型复制后俩个变量完全独立,之后任何一方改变都不会影响另一方;引用类型复制的是引用(即指针),之后的任何一方改变都会映射到另一方。
不少人对参数都是按值传递的感到困惑,因为访问变量有按值和按引用两种方式。下面就来看看有何不同:
这一段很重要:我们可以把ECMAScript函数的参数想象成局部变量。在向参数传递基本类型的值时,被传递的值被复制给一个局部变量(即命名参数,或者用ECMAScript的概念来说,就是arguments对象中的一个元素)。在向参数传递引用类型时,会把这个值在内存中的地址(指针)复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。
1、按值传递
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count); //按值传递 num = count
alert(count); // 20, 没变化
alert(result); //
很好理解,因为是按值传递的,传递完后俩个变量各不相干!
2、按引用传递
function setName(obj) {
obj.name = "Nicholas";
}
var person = new Object();
setName(person); // obj = person
alert(person.name); // "Nicholas" 看起来是按引用传递,但千万不要以为是按引用传递~~~
当 var person = new Object(); 时,可以用下图表示变量和对象的关系:

当调用函数 setName(person); 时,下图可以表示全局变量person和局部变量obj的关心:

以上代码中创建一个对象,并将其保存在变量person中。然后,这个变量被传递到setName(obj)函数中之后就被复制给了obj。在这个函数内部,obj和person引用的是同一个对象。换句话说,即使ECMAScript说这个变量是按值传递的,但obj也会按引用来访问同一个对象。于是,在函数内部为obj添加name属性后,函数外部的person也将有所反应;因为这时的person和obj指向同一个堆内存地址。所以,很多人错误的认为:在局部作用域中修改的对象会在全局对象中反映出来,就说明参数是按引用传递的。
为了证明对象也是按值传递的,我们再来看看下面这个经过修改的例子:
function setName(obj) {
obj.name = "Nicholas";
obj = new Object(); //改变obj的指向,此时obj指向一个新的内存地址,不再和person指向同一个
obj.name = "Greg";
}
var person = new Object();
setName(person); //你看看下面,相信我也是按值传递的了吧
alert(person.name); //"Nicholas"
当创建obj对象 obj = new Object(); 时,来看看这时person和obj的关系图:

这个例子与前一个唯一的区别,就是setName()函数中添加了两行代码: obj = new Object(); 用来改变obj的指向; obj.name = "Greg"; 用来给新创建的obj添加属性。如果是按引用传递的,那么person就会自动被修改为指向新创建的obj的内存地址,则person的name属性值被修改为"Greg"(这句话之前说的有误,引用传递的是指针的值,obj=new Object()改写了自己的指向,并不会影响到person的指向,这种方式就是按引用传递。即使不把对象赋值给函数的参数,obj改写指向对person也没影响,见下面代码)。但是,当访问person.name时,显示的结果为"Nicholas"。这说明即使在函数内部修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后被立即销毁!
推翻以上都是按值传递的结论:
var person=new Object();
var obj = person; // 赋值
obj.name="ABC";
obj=new Object();
obj.name="BCD";
console.log(person.name);// ABC 并没有影响person的指向
综上所述,还是觉得参数传递对象时是按引用传递的,欢迎指正!
JS中函数参数值传递和引用传递的更多相关文章
- 验证python中函数传参是引用传递
定义: 值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数. 引用传递(pass by reference)是指在 ...
- vue中动态加载组件+开发者模式+JS参数值传递和引用传递
今天写vue里面通过接口反参动态加载组件时候 跟着同学...学习到了 一.先说说vue 内置组件 component 的用法 component组件可以来专门用来进行组件的切换,使用is来绑定你的组件 ...
- JS 中没有按地址(引用)传递,只有按值传递
很多人,包括我,受书本知识消化不彻底的影响,认为 JS 中参数有两种传递方式:数字.字符串等按值传递:数组.对象等按地址(引用)传递.对此种观点,我们要谨慎. var v1 = [] var v2 = ...
- 晨叔技术晨报: 你真的搞懂JS中的“值传递”和“引用传递”吗?
晨叔周刊,每周一话题,技术天天涨. 本周的话题是JS的内存问题(加入本周话题,请点击传送门). 图 话题入口 今天的技术晨报来,就来谈谈JS中变量的,值传递和引用传递的问题.现在,对于很多的JSer来 ...
- java中函数是值传递还是引用传递?
相信有些同学跟我一样,曾经对这个问题很疑惑.在网上也看了一些别人说的观点,评论不一.有说有值传递和引用传递两种,也有说只有值传递的,这里只说下个人见解 先看一个例子 public class Test ...
- [转]Python中函数的值传递和引用传递
首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...
- 深入理解python中函数传递参数是值传递还是引用传递
深入理解python中函数传递参数是值传递还是引用传递 目前网络上大部分博客的结论都是这样的: Python不允许程序员选择采用传值还是传 引用.Python参数传递采用的肯定是"传对象引用 ...
- Java中的值传递和引用传递
这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...
- JavaScript 函数参数传递到底是值传递还是引用传递
tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里 ...
随机推荐
- NI Vision for LabVIEW 基础(一):NI Vision 简介
NI Vision 控件模板 Vision控件模板位于LabVIEW控件模板的最顶层,由一下元素组成: IMAQ Image.ctl—该控件是一个类型定义,用于声明图象类型的数据.在VI的前面板中使用 ...
- Linux系统操作指令汇总
1.系统配置 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIO ...
- openfire+smack 实现即时通讯基本框架
smack jar下载地址 http://www.igniterealtime.org/downloads/download-landing.jsp?file=smack/smack_3_2_2.zi ...
- Pangolin学习
0.1. 资料 0.2. 使用说明 0.3. HelloPangolin 0.4. Plot data with ros 0.1. 资料 泡泡机器人 github example opengl中摄像机 ...
- Java的CLASSPATH
在JDK安装好后,要设置两个变量Path和Classpath,Path是操作系统要求的,这里不谈了,而classpath是Java虚拟机要求的这里做一个详细的解释. 一.classpath的作用 == ...
- css 3d 基础知识
css3d 总结 3d transform (3D变形)(rotate skew scale translate) 基础知识 perspective (视距,景深) perspective-origi ...
- 学习笔记:JavaScript-进阶篇
1.二维数组 二维数组的表示: myarray[ ][ ] var myarr=new Array(); //先声明一维 for(var i=0;i<2;i++){ //一维长度为2 ...
- background新增的N个强悍功能!!!
background在CSS3中新增样式: [ ] 首先我们先回顾下background的原有样式: background-color 背景颜色 相关属性值: 关键字:red,blue,yellow等 ...
- Java学习笔记——排序算法之进阶排序(堆排序与分治并归排序)
春蚕到死丝方尽,蜡炬成灰泪始干 --无题 这里介绍两个比较难的算法: 1.堆排序 2.分治并归排序 先说堆. 这里请大家先自行了解完全二叉树的数据结构. 堆是完全二叉树.大顶堆是在堆中,任意双亲值都大 ...
- maven私服nexus搭建(windows)
1.下载nexus 地址:https://www.sonatype.com/download-oss-sonatype 下载相应版本的zip包. 2.安装nexus 下载完成后,解压到本地任意目录. ...