了解参数的传递以前咱们来复习下变量的类型,JavaScript中的变量有5个基本数据类型(Undefined, Null, Boolean, Number, String)和引用数据类型(Object,Function,Array等)。函数
// 声明一个String类型的变量spa
var str = "string";
// 声明一个引用类型的变量,并添加属性code
var person = new Object(); person.name = "Jeremy";
两者的区别主要在于对变量内容保存的方式,基本类型的变量中存储的就是简单的数据段,而引用类型变量存储的是指向对象的引用,好比:对象
// 基本类型的变量复制,能够看出基本类型变量存储的就是变量的值blog
var num1 = 5; var num2 = num1; console.log(num2); //5
num1的5与num2的5是彻底独立的,这两个变量能够参与任何操做而不会相互影响。下图可以形象的展现复制过程。ip
// 引用类型的变量复制,能够看出引用变量中存储的是指向对象的引用rem
// Object对象存储于堆中,而obj1和obj2分别存储了指向此Object对象的引用get
var obj1 = new Object(); obj1.name = "Jeremy"; var obj2 = obj1; obj2.name = "James"; console.log(obj1.name); //James
首先变量obj1保存了一个对象的新实例,又给obj1添加一个新属性name,后obj1对象被复制给了obj2,obj2也有了name这个属性,而且访问的地址是跟obj1的name属性是一个地址,因此当修改了obj2的那么属性的话,那obj1的name属性也会改变。下图展现了保存在变量对象中的变量和保存在堆中的对象之间的这种关系。string
在JavaScript中不管是基本类型仍是引用类型,函数参数都是按值传递的,先来看基本类型:it
function test(num) { num += 10; return num; } var num = 10; var res = test(num); console.log(num); //10 外部变量并未受到影响 console.log(res); //20
接下来看引用类型:
function setName(obj) { obj.name = "James"; } var person = new Object(); person.name = "Jeremy"; setName(person);
console.log(person.name);//James 影响到了外部引用变量
乍一看,这不就是按引用传递吗?怎么会是按值传递呢?之因此是按值传递是由于当调用setName(person)的时候,其实是把person所指向的对象的引用进行了复制,而后传递给了setName函数,这样在函数setName内部对此引用进行操做时候是会影响到此引用所指向的对象,即外部person所指向的对象。
总的来讲,基本类型的参数传递复制的是具体的值,而引用类型的参数传递复制的是这个引用变量存储的对对象的引用。
为了进一步证实引用类型的参数传递是按值传递而不是按引用传递的,请看:
function setName(obj) { obj.name = "James"; obj = new Object(); obj.name = "Leon" } var person = new Object(); person.name = "Jeremy"; setName(person); console.log(person.name);//James
以上代码输出的是James,若是是按引用传递,那么以上代码输出的是Leon。实际上,当执行obj.name = "James"的时候,引用所指向的对象的值已经发生了改变,当在对obj进行覆盖的时候,obj的值是一个指向局部对象的引用,而这个引用没法对外部的对象产生影响,而且此对象会在函数执行结束以后销毁。