首先,ECMAscript中所有的函数是按照值传递的
这意味着函数外的值会被复制到函数内部的参数中,就类似于一个变量。如果是原始值,那么就跟原始值变量复制一样,如果是引用值,那么就跟引用值变量的复制是一样。(红包书上的原话)
一个题目
如果对这个问题的答案不是很清楚,需要去测试的话,这边文章很值得看下去。我的理解如果有问题,希望大家能够指出来。
function test(a) {
a = a + 10
console.log(a)
}
var a = 10
test(a)
console.log(a);
对是值传递还是引用传递的分析
在按值传递时,只会被复制到一个局部变量,就是函数外面的变量,在作为函数实参传递时会在函数内部对实参和形参存在一个赋值操作。在按照引用传递时值在内存中的位置会被保存在一个局部变量,这个局部变量被用在函数内部,也就是内外的实参形参是一个值,所以函数内部的修改会影响到函数的外部。js中函数是按照值传递的。有了这个结论,这时候,上面的问题,就迎刃而解了。
function test(a) {
a = a + 10
console.log(a) // 20
}
var a = 10
test(a)
console.log(a); // 10
- 首先,形参相当于是在函数内部声明的局部变量 var a
- 值传递,相当于把实参a = 10 给了形参a一份副本,把局部变量a赋值为了10
- 所以修改是在a这个局部变量上的修改,局部变量值加一变成了20, 打印出20
- 而对区局变量a没有任何影响
对于上面的解释没有什么问题,但是当传递的一个引用类型的值时,就似乎没有那么清楚了
function setName(obj) {
obj.name = 'lisi'
}
let person = {
name: 'zhangsan'
}
setName(person)
console.log(person.name); // lisi
这次我们把一个对象作为函数的参数进行传递,我们来分析
- 首先我们创建了一个person对象,里面有name属性
- 把对象传递到函数中,执行了类似于var obj = person的赋值操作。
- 结果,有点意外的,对于obj的修改,也反映到了person上面
- 对应的关系如图
这个结果是因为js的赋值操作的结果是使得obj和person同时指向了堆内存上的对象,所以函数内部修改了obj会反映到函数外部的person对象上,因为修改的是堆内存上的对象。但是函数内部修改对象的影响到了全局,并不代表着参数是按照引用来传递的。下面我们来证明这个结论
function setName(obj) {
obj.name = 'lisi'
obj = {}
obj.name = 'wangwu'
}
let person = {
name: 'zhangsan'
}
setName(person)
console.log(person.name); // lisi
上述的例子中在函数内部修改了形参为一个空对象,结果仍然是lisi,我们来一步步分析,这个例子是怎么能够说明是值传递的呢,如图
- 首先在函数内部,把形参obj修改为了一个空对象,就相当于这样相当于修改了obj指向的堆内存对象,指向了一个空对象,跟person不再指向同一个对象
- 然后修改其name属性为wangwu,但是这个时候修改name只是修改局部obj指向的新的堆内存,对person没有任何的改变。
- 因为是值传递,所以只是进行了obj的简单赋值为person,因为js的引用赋值是修改指向的内存,所以obj的变化显示在了person上。而如果是引用赋值的话,就是obj两个是绑定在一块的,obj指向了新的空对象,person必定也只想新的空对象,显然没有,person仍然指向原来的对象。由此可见,是值传递的。
总结,
- js函数传参是值传递的,无论是引用类型还是基本类型
参考文献:《javascript高级程序设计》
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!