Javascript 之《函数传参到底是值传递还是引用传递》
前言
这个问题其实困惑了我好久,但是在实际使用中总是得过且过,不想去深究。由于这种态度,在学习 Javascript 过程中,水平一直都是出于半桶水状态,很多概念和原理似懂非懂,模糊不清。
所以,写了一系列的《Javascript 之 ...》就是为了端正态度,认真地研究一下 Javascript 的特性和原理,夯实基础。
今天,这一篇探究的是函数传参的问题:函数传参到底是传值还是传的引用?
1.如果是引用传递
var name = 'JS'; function changeName(name){ name = 'Javascript';
console.log('name changed: '+name) } changeName(name); // name changed: Javascript console.log(name); // 'JS'
为什么 name 没有变呢?
如果是引用传递的话,name 应该是会发生变化的。这么说应该是值传递?
也许你下意识也觉得没变是正常的,但这是因为你的经验告诉你的。我们暂且按下不表,看看下一种可能性。
2.如果是值传递
var obj = {name: 'JS'}; function changeObjName(obj){ obj.name = 'Javascript'; console.log('Obj.name changed: '+obj.name); } changeObjName(obj); // Obj.name changed: Javascript console.log(obj); // {name: 'Javascript'}
为什么这一次传入的参数被改变了?不是值传递吗?这么说是引用传递了?
那上面的例子又是怎么回事?开始一头雾水了...
3.到底是值传递还是引用传递??
其实在 Javascript 的世界中,函数传参并不是一定是一种传参方式,主要依据传入的参数而定。主要有两种情况:
1. 如果是值类型
基本数据类型的变量基本上都是值类型,例如字符串,数值,布尔值等。
值类型的传参是值传递,函数内对这种类型参数的修改不会影响到原来传入的值。
2. 如果是引用类型
复合数据类型如对象,数组等都是引用类型。
引用传参是引用传递,函数内对这种类型参数的修改都会影响到原来传入的值。
4.深入函数传参的机制
其实函数接受参数之前,会先在函数作用域内创建一个局部变量,并把传入的参数赋予创建的局部变量,如果值类型传递,就是重新开辟一块内存存储传入变量的值,并把新创建的变量指向此内存地址,因此对此变量的修改并不会影响到外部变量的值;
如果传入的不是值类型,则仅仅是对变量进行引用赋值操作,只是把新创建的局部变量指向外部变量的地址,因此对局部变量的修改就相当于对外部变量的修改。