关于js参数传递矛盾新理解

之前看了很多人的解释,说js中,函数的参数传递都是值传递中不理解。

他们无非举了两个例子

在这两个例子中,第二个例子可以看出参数是由值传递的。因为函数内对象的变化没有影响到函数外对象的变化。但是在第一个例子中,我们却发现,函数内和函数外都指向了一个地址。但是博主并没有说明

既然是值传递,为什么参数里面的改变却影响了外面的值。博主只解释了第二个例子是值传递,却没有解释第一个例子为什么会出现这样的原因,只是一句两个变量指向一个对象

就一笔带过,我觉得这个并没有解决大多数人的理解。所以我觉查看了js高级程序设计的原话。

《js高级程序设计》上是这样叙述参数传递的:所有函数的参数都是按值传递的

这段话摘抄自第四章的第一章节的传递参数。

这里解释一下,值传递。值传递就是传进来的参数中,我们传递的是一个值,而不是一个指针。

其实。为什么第一个例子中,两个变量指向的是一个对象。原因很简单,就是因为这里的参数传递的本来就是一个地址。这似乎和之前说的所有参数都是值传递相违背。觉得既然是值传递应该传递的是一个对象,然后在参数中建立一个这个对象的副本。其实这是一种错误的理解。

这里需要解释一下值传递,什么是值传递。值传递就是说,参数传递的是其中的值,然后这个值在函数中会建立一个副本,在函数内操作参数的其实是这个副本,而不是函数外传递的变量。

而js函数机制中,函数传递的参数,会把参数的值存储在arguments(这个数组是函数对象自带的数组,用来保存参数值)这个数组中,我们操作的参数,其实是这个数组中的值。这里就从本质上解释了js函数是值传递。

了解这个我们就可以说为什么第一个例子中所出现的现象了。因为,对象参数传递的,本身就是一个地址,他并不是一个对象。

这里可能还会疑惑,既然是传递的地址为什么还叫做值传递。

我们可以通过一幅图来理解

在这里,当a被当做参数时,a中的值也就是地址,被传递进了arguments这个数组中,而值传递和引用传递,指的其实对于这个地址来说的。

值传递,   就是传递a的值,a的值其实就是指向Object的地址。

如果是

引用传递,传递的是a的地址,也就是指向a的地址。如果了解c语言就可以对这个明白了。

a中保存的是指向对象的一个指针,在引用传递中,会传递一个指向a的指针。

所以这就解释了为什么会出现两个例子中这个看似很矛盾的的原因了。

值传递还是引用传递,他所说的并不是a指向的对象的传递方式,而仅仅是a的传递方式。

这是自己的理解,我觉得这样的理解对我来说才彻底解释了我之前感觉两个例子的矛盾的原因

时间: 2024-10-11 05:44:18

关于js参数传递矛盾新理解的相关文章

js参数arguments的理解

原文地址:js参数arguments的理解 对于函数的参数而言,如下例子 function say(name, msg){ alert(name + 'say' + msg); } say('xiao', 'hello'); 当调用say()函数时,函数会创建arguments参数数组,这个数组跟形参没有多大关系,即使没有形参, function say(){ alert(arguments[0] + 'say' + arguments[1]); } say('xiao', 'hello');

js 模块化的一些理解和es6模块化学习

模块化 1 IIFE 2 commonjs 3 浏览器中js的模块化 4 简单理解模块加载器的原理  5 es6 之前在参加百度前端技术学院做的小题目的时候,自己写模块的时候 都是写成立即调用表达式(IIFE)的模式,比如单个功能的时候当时想到是不会涉及到全局变量的污染,在封装基础的模块(比如里面的表单验证功能) (function(win){ var obj = {}; function add() { console.log("add"); } obj.add = add; win

JS中的prototype理解

JS中的phototype是JS中比较难理解的一个部分 本文基于下面几个知识点: 1 原型法设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个类B,这个类是以A为原型的,并且能进行扩展.我们称B的原型为A. 2 javascript的方法可以分为三类: a 类方法 b 对象方法 c 原型方法 例子: function People(name){  this.name=name;  //对象方法  this.Introduce=functi

JS中异常处理的理解

[转]JS中异常处理的理解 JS里的异常处理 JS的异常捕获与处理可以从它的 try-catch 语法结构说起,具体形式如下: try{ ... //异常的抛出 }catch(e){ ... //异常的捕获与处理 }finally{ ... //结束处理 } 其中,try块: try块包含的是可能产生异常的代码,在这里面直接或者在里面通过调用函数里间接抛出的异常都可以捕获到.部分浏览器还可以找到具体抛出的位置.详见e.stack. catch块: catch块,是捕获异常,并处理异常的地方,包括

关于erlang中的进程字典(process dictionary)的新理解及其访问速度 (copy来的)

之前对于erlang的进程字典了解的不够清楚,只是知道put().get()函数,即存值和取值,而每个put.get中都有自己的一对Key--Value(键值对)与之对应.一个Key对应一个Value.在erlang中,启动进程节点之后,进程字典的put.get的值是对缓存的处理,而对数据库的操作,相当于是对硬盘的一个操作,可以理解成是一个数据的备份. 举个简单的例子:在游戏中都有好友操作,启动服务之后,玩家点击添加好友操作,进程的节点已经开启,先从内存中获取玩家的进程字典的Value的值,这里

js post 方式 新开窗口

js中一般新打开窗口很简单直接window.open(url);就可以了, 但是由于我希望传递参数到服务端,而且参数看起来很长一串,而且get方式的提交参数长度是有限制的,因此我有以下需求: 1,js中实现post提交 2,返回的页面在新窗口显示 首先我是这么做的: $.ajax({ type: "POST", url: '${contextPath}/analyse/detail.do', data: {carNum :carNum,ids:refIds}, success: fun

Node.js V0.12 新特性之性能优化

v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化. 本文会介绍其中最值得注意的几个. http://www.infoq.com/cn/articles/nodejs-v012-optimize-performance?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk Node.js和

数据库水平分库,垂直分库的新理解

水平分库:当数据量巨大时,将数据放到不同的表中,比如表1,表2,表3,...: 垂直分库:当一张表的字段太多,可拆分出一张或多张分表,根据主键唯一标示: 新理解: 垂直分库:当一张表中字段不多,当某些字段长度过长,表占用空间很大,检索表的时候需要执行大量的IO(数据库检索的本质是对硬盘中的文件进行io访问), 此时可以考虑对长度较长的字段进行拆分,单独成表,用原表主键进行唯一标示. 相反: 当数据库记录数不多,但字段较多,可对部分字段进行整合,比如用户的信息(电话,手机号...),以json字符

接口测试的新理解

最近一直关注接口测试的方方面面. 慢慢的对接口测试的一些更细节的方面有着一些理解. 简单的说,接口测试的过程中需要关注的一些是: 1. 接口的有效性. 2. 接口数据的冗余性. 先说有效性: 有效性的意思在于接口数据的重用,因为在测试的过程中遇到了一种情况,大概的情况是: App上有一个页面,做成了两个Activity,在app上展示为一个页面,上方是个人信息的图片,头像和评论数等一系列的信息.下方是详细信息的一些内容. 不可以理解的是前端做成了两个Activity,A和B ,两个Xml布局,