js函数中参数的传递

时间:2023-02-20 18:07:19

数据类型

在 javascript 中数据类型可以分为两类:

  • 基本类型值 primitive type,比如Undefined,Null,Boolean,Number,String。
  • 引用类型值,也就是对象类型 Object type,比如Object,Array,Function,Date等。

变量的复制

众所周知,js中变量的基本类型和引用类型保存方式是不同的,这也就导致变量复制时也就不同了。如果从一个变量向另一个变量复制基本类型的值时,会将前者的值克隆一个,然后将克隆的值赋值到后者,因此这两个值是完全独立的,只是他们的value相同而已。

var num1 = 10;
var num2 = num1;
console.log(num2);//10

上面的num1中被保存的值为10,当把num1的值赋值给num2时,num2的值也为10。但是这两个10是完全独立的,num2中的10只是被克隆出来的,相当于我写了一个word文档,把它放到了num1的文件夹中,然后我再复制这个word文档,就叫word副本吧,然后把这个副本放到num2的文件夹下,这两个word文档是完全一样的,修改任何一个都不会影响两一个。

num2 += 1;
console.log(num1); //10
console.log(num2); //11

从上面可以看出修改num2的值,num1的值未发生变化。再来看下引用类型的复制。当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

第一次打印出的结果为“111”,这个我们很容易理解,但是第二次打印出来的是“222”,有点莫名其妙了。这就是引用类型和基本类型的不同之处了。复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了。将obj1的值复制给obj2,而这个值的副本实际上是一个指针,这个指针指向存储在堆中的一个对象,也就是说创建了一个新的内存地址传给了obj2,obj1和obj2两个变量同时指向了同一个Object,当去改变这个对象时,他们的值都会改变,也就是说他们中任何一个作出的改变都会反映在另一个身上。下面的简易图可能更明了些。

js函数中参数的传递

函数参数的传递

《js高级程序设计》上是这样叙述参数传递的:所有函数的参数都是按值传递的,也就是说把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。所以如果能理解变量的复制,那么参数的传递也就很简单了。还是先从基本类型举例说明吧。

js函数中参数的传递
js函数中参数的传递
var count = 10;
function num(num1){
num1 = 1;
return num1;
}
var result = num(count1);
console.log(result);//1
console.log(count);//10,并未变成1
 
js函数中参数的传递
js函数中参数的传递

这个例子很容易理解,实际就是创建了一个count的副本,然后把count的值传入参数中,因为函数中定义了参数的值,所以1就将10覆盖了,最后的result返回1,而count并未发生变化。看一个有关传递对象的例子。

js函数中参数的传递
js函数中参数的传递
var person  = {
name : "Tom"
};
function obj(peo){
peo.name = "Jerry";
return peo;
}
var result = obj(person);
console.log(result.name);// Jerry
console.log(person.name);// Jerry
js函数中参数的传递
js函数中参数的传递

在上面的例子中,把person复制传入obj()中,peo和person指向了同一个对象,而在peo中修改了name属性,其实修改了它们共同指向的对象的name属性,相对应的外部person所引用的name属性也就改变了,所以打印出来的为Jerry。其实这个乍一看,感觉引用类型的参数是按照引用传递的,这就是我最初犯得错误。再来看一个例子。

js函数中参数的传递
js函数中参数的传递
var person = {
name : "Tom"
};
function obj(peo){
peo = {
name : "Jerry"
};
return peo;
}
var result = obj(person);
console.log(result.name);// Jerry
console.log(person.name);// Tom
 
js函数中参数的传递
js函数中参数的传递

上面的例子中,在函数中重新定义了一个对象,也就是现在堆内存中有两个对象,外部的person指向的是老的对象,被传入参数后指向的是新定义的对象,所以调用后返回的值是新定义的对象的值。如果是参数是按引用传递的,那么person.name打印出来的结果为Jerry,从这点可以得出参数是按值传递的(有的地方叫做按共享传递)。

我们拿老罗推荐的《人类简史》把它形象化,描述的不太好。简史的第一章标题是“认知革命”,我们把它名字改为“person”根据后面的页码数可以直接找到“认知革命”的内容“也就是peoson所指向的对象”,第二章是“农业革命”,我们把它为“result”,其分目录有一节“记忆过载”(改名为“peo”),同样可以直接根据页码找到这一节内容。现在我们把“person”复制到“peo”中,第二章中的“peo”这一节就变成了“person”,而我们根据第一章中的“peoson”找到的还是第一章的内容,这是因为它们指向了不同的内容板块,互不干扰。在这里,堆内存就是每章的内容,而第一章和第二章内容是2个不同的对象,而这两者互不相干,因此打印外部person.name时,结果仍是以前的对象的属性值。

结论

总而言之,在js中参数都是按值传递的。我写例子粗糙了些,《javascript高级程序设计》中的例子描述的更清晰一些,更易理解。

来自https://home.cnblogs.com/u/open-wang/

js函数中参数的传递的更多相关文章

  1. python函数中参数的传递

    Python唯一支持的参数传递方式是『共享传参』(call by sharing)多数面向对象语言都采用这一模式,包括Ruby.Smalltalk和Java(Java的引用类型是这样,基本类型按值传递 ...

  2. 《从零开始学Swift》学习笔记(Day 20)——函数中参数的传递引用

    原创文章,欢迎转载.转载请注明:关东升的博客 参数的传递引用 类是引用类型,其他的数据类型如整型.浮点型.布尔型.字符.字符串.元组.集合.枚举和结构体全部是值类型. 有的时候就是要将一个值类型参数以 ...

  3. js函数的参数

    js函数的参数: js是弱类型的编程语言,调用函数时既不在乎函数的参数,也不在意参数的类型 即便你定义的函数值接受两个参数,在调用这个函数时也未必一定要是两个参数.可以传递一个.三个甚至不传递参数,而 ...

  4. C++指针作为函数的参数进行传递时注意的问题

    应注意问题: 当指针作为函数的参数进行传递的时候,本质上还是进行的"值传递",也就是复制了一个新的指向该地址的指针变量. 只有在被调函数中,对指针进行引用操作,才可以达到不需要返回 ...

  5. js函数中获得当前被点击元素

    问题描述:在html页面中点击<a>或者’按钮‘,进入js中的函数,在js函数中获得被点击那个<a>或‘按钮’元素 解决方法:方法一: html中: <a>标签:& ...

  6. 在JS函数中执行C&num;中的函数、字段

    1.调用字段 cs文件的代码: ; protected void Page_Load(object sender, EventArgs e) { id = ; } js页面的代码: function ...

  7. hibernate的dao中参数的传递取值

    hibernate的dao中参数的传递取值 private Query setParameter(Query query, Map<String, Object> map) { if (m ...

  8. js函数定义 参数只要写名称就可以了

    js函数定义  参数只要写名称就可以了 以下为标准: function add(type)  { } 不要写成下面这个样子 function add(var type)  { } 哎 妹的  老何ja ...

  9. python函数中参数是如何传递的?

    python中一切皆对象,函数中参数传递的是对象的引用. 1在函数中改变变量指向的对象,即指向不同对象. 当在函数中修改传递进来的变量指向另一个对象时,实参的对象不会改变. >>> ...

随机推荐

  1. 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(2)

    作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...

  2. diff生成补丁与patch打补丁

    1.使用diff生成补丁: diff是Linux下的文件比较命令,参数这里就不说了,直接man一下就行了,不仅可以比较文件,也可以比较两个目录,并且可以将不同之处生成补丁文件,其实就是一种打补丁的命令 ...

  3. Linux 命令收集

    http://www.cnblogs.com/tzhangofseu/archive/2011/12/17/2290955.html vim :r filename :sh  enter shell ...

  4. 发布一个开源极致的javascript模板引擎tpl&period;js

    tpl.js(大家直接去https://git.oschina.net/tianqiq/tpl.js这个上面看) 简介 tpl.js是一个比较极致(极小,极快,极简单)的js模板引擎,可以在各种js环 ...

  5. C&num;时间戳与时间互转

    /// <summary> /// 时间戳转成时间类型 /// </summary> /// <param name="timeStamp">& ...

  6. 调用office COM出现不会退出的问题

    症状 在使用.net调用 Microsoft Office 应用程序时,Office 应用程序在调用Quit方法时不会退出. 原因 Visual Studio.NET 从托管代码调用 COM 对象时, ...

  7. 对比springmvc与struts2

    转载:http://blog.csdn.net/chenleixing/article/details/44570681 1.Struts2是类级别的拦截, 一个类对应一个request上下文,Spr ...

  8. vs2015如何设置类或函数前不显示引用的数量

    这几天,从vs2012换成vs2015,感觉15版本增加了一个类或函数前提示引用的数量,这个感觉很别扭,如何取消显示这个呢? 问题如下: 取消显示这个引用的步骤: 找到菜单栏: 工具 ---> ...

  9. Delphi7编译时,发生Access violation at address 00A7B628 in module &&num;39&semi;dcc70&period;dll&&num;39&semi;&period; Read of address 00000000&period;&lpar;Delphi6升级到Delphi7)

    最近接了一个项目,要求使用Delphi7来开发程序,可是由于我们之前均使用delphi6来开发程序的,而且Delphi6使用很长时间了,积累并改造了第三方控件很成熟了: 故把Delphi6的控件移植( ...

  10. &lbrack;OS&rsqb; 操作系统基本类型

    ·批处理系统:(用户脱机使用.成批处理.多道程序运行) 批处理系统,又名批处理操作系统.批处理是指用户将一批作业提交给操作系统后就不再干预,由操作系统控制它们自动运行.这种采用批量处理作业技术的操作系 ...