先看一道JS的笔试题:

var setObj=function(o){o.name="xiaoming";o={};o.name="xiaohong";
}
var p={name:"xixi",age:24};
setObj(p);
console.log(p);

答案是{name:xiaoming,age24};

在JavaScript中函数参数默认为引用类型。

在阅读本章节之前建议参阅一下两章节:
1.值类型可以参阅javascript的值类型一章节。
2.引用类型可以参阅javascript的引用类型一章节。
一.函数传递值类型:
代码实例如下:

function addNum(num){ num+=10; return num;
}
var num=10;
var result=addNum(num);
console.log(num);
console.log(result);

以上代码的弹出值分别为:10和20,下面进行一下分析:
声明变量num并复制为10,这个是num是一个值类型,当为函数传递参数的时候,是将此值复制一份传递给函数,所以在函数执行之后,num本身的值并没有被改变,函数中被改变的值仅仅是一个副本而已。
二.函数传递引用类型:

1 function setName(obj){
2   obj.name="青岛新锐";
3 }
4 var web=new Object();
5 web.name="蚂蚁部落";
6 setName(web);
7 console.log(web.name);

以上代码的弹出值是:“青岛新锐”,下面进行一下分析:
声明一个对象web,它是一个引用类型,当为函数传递参数的时候,是传递的web对象的引用,也就是此对象的内存地址,所以在函数中修改属性的对象就是函数外面创建的对象本身。
三.加深理解:

1 function setName(obj){
2   obj.name="青岛新锐";
3   obj=new Object();
4   obj.name="蚂蚁部落";
5 }
6 var web=new Object();
7 setName(web);
8 console.log(web.name);

以上代码的弹出值是:青岛新锐,很多人可能会以为将会弹出“蚂蚁部落”,下面进行一下简单的分析:
在函数外面创建一个对象,并将对象的引用赋值给变量web,web中存储的是对象在内存中的存储地址,当为函数传递参数的,就是传递的在函数外面创建的对象的地址。在函数中,为外面创建的对象创建一个自定义属性name并赋值为“青岛新锐”,然后又创建一个新的对象,并将新对象的地址赋值给obj,这个时候obj指向的并不是函数外面创建的对象,所以外面对象name属性不会被改变。

这样写对于其他语言的程序员来说是很难接受的,我们在实际的开发中避免这样的写法,因为这样会造成全局作用域污染。最近在读《javascript高级程序设计》时碰到了js传递方式的问题,花费了些时间,不过总算明白了。

数据类型

在 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的值未发生变化。再来看下引用类型的复制。当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。

var obj1 = {name : "111"
};
var obj2 = obj1;
console.log(obj2.name); //111obj2.name = "222";console.log(obj1.name); //222

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

函数参数的传递

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

var count = 10;
function num(num1){num1 = 1;   return num1;
}
var result = num(count1);
console.log(result);//1
console.log(count);//10,并未变成1
 

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

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

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

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
 

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

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

结论

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

转载于:https://www.cnblogs.com/Unknw/p/6512588.html

js函数中参数的传递相关推荐

  1. 函数中参数的传递的几种方式与区别

    关于C与C++中函数的变量传递方式的总结归纳 其大致可以分为传递参数,传递地址,传递数组,传递引用类型 1 传递数值 2. 传递地址即操作指针变量(C语言的指针操作) 3.传递数组 4. 传递引用类型 ...

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

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

  3. 函数中参数有数组时注意的小问题(不一定要传递数组长度,不用返回数组,可以在函数中改变数组元素值)

    函数中参数有数组时注意的小问题: 1.不一定要传递数组长度 2.不用返回数组,可以在函数中改变数组元素值 通过下面这个小例子来验证: #include<iostream> #include ...

  4. idea中js函数中使用EL表达式报错expression expected以及参数underfined的问题.md

    EL表达式显示错误expression expected问题: ​ 这段代码在MyEclipse中没有问题,因为idea的严格代码检查,这里会显示expression expected的错误,原因是因 ...

  5. 详解 js 函数中的 arguments

    详解 js 函数中的 arguments 1.什么 arguments 简单来说:arguments 是一个对应于传递给函数的参数的类数组对象 arguments 对象是所有(非箭头)函数中都可用的局 ...

  6. JS函数的参数(arguments)的使用

    JS函数的参数在function内可以用arguments对象来获取. 参数的调用有两种方式: 1.期望参数的使用. 2.实际传递参数的使用. 应用举例: function Test(a, b){ v ...

  7. Java中将函数作为参数进行传递

    最近一直在做一个项目的前端,使用的框架是vue,还有一些基于vue的组件库,学习了很多js的相关内容.今天突然想看一下Java,发现好久不看忘记了许多,还是希望每天晚上可以写点博客,当做学习,复习的方 ...

  8. python爬取js加载的数据_Python爬虫学习,记一次抓包获取js,从js函数中取数据的过程...

    昨天有小伙伴找我,新浪新闻的国内新闻页,其他部分都是静态网页可以抓到,但是在左下方的最新新闻部分,不是静态网页,也没有json数据,让我帮忙抓一下.大概看了下,是js加载的,而且数据在js函数中,很有 ...

  9. js与python 抓包_Python爬虫学习,记一次抓包获取js,从js函数中取数据的过程

    昨天有小伙伴找我,新浪新闻的国内新闻页,其他部分都是静态网页可以抓到,但是在左下方的最新新闻部分,不是静态网页,也没有json数据,让我帮忙抓一下.大概看了下,是js加载的,而且数据在js函数中,很有 ...

最新文章

  1. tensorflow学习笔记二——建立一个简单的神经网络拟合二次函数
  2. [转载]基于Aaf的数据拆分
  3. Enterprise Architect 8.0 注册码及其使用教程
  4. springboot系列六、springboot配置错误页面及全局异常
  5. 奇门遁甲鸣法 第四章 正格
  6. 计算机考研机试指南(九)——搜索(百鸡问题、ABC、胜利大逃亡、迷宫问题、C翻转、旋转矩阵、字符串匹配、)...
  7. 易宝典文章——玩转Office 365中的Exchange Online服务 之二十八 怎样过滤病毒***邮件...
  8. Unity到VRay的渲染方法
  9. 视频号推荐机制:可社交裂变冷启动
  10. PAT Basic 1055
  11. 平面设计中都有哪些风格?常用的风格有哪些?
  12. JBX+WL8+Struts国际化中的一些问题
  13. Phpspreadsheet 中文文档(六)读写文件+读取文件
  14. 【案例分享】项目施工进度报告 – 树形报表
  15. MATE9系统升级提示服务器,华为Mate9用ADB调试功能禁用系统更新去右上角提示更新的数字角标1...
  16. CVPR2021投稿流程
  17. H3C交换机端口镜像原理
  18. 投身物联网创业6个月,我是如何选择 IoT 物联网平台的?
  19. Linux命令大全【转载】_追逐梦想的顾咏丰_新浪博客
  20. 每日一笑(shell)--每日备份文件-20190919

热门文章

  1. [BUUCTF-pwn]——picoctf_2018_can_you_gets_me
  2. 关于优酷开发SDK之setOnSeekCompleteListener
  3. 优酷开放sdk-setOnerroListener
  4. 同一Word文档不同尺寸(纸张)页面的混排方法
  5. 用Macbook开发桌面应用,使用Alamofire链接.Net Core Webapi的注意事项!
  6. 软测homework2
  7. 【FPGA】相关介绍
  8. DHTML4(select与checkbox应用)
  9. Eclipse 常用快捷键
  10. 『流畅的Python』第12章:继承的优缺点