javascript之理解参数按值传递

初读js高程第三版看到第四章下的参数传递这一小节时,没理解他所说的所有参数传递都是以值类型传递。如今细细品读,才发现当初才疏学浅没看懂不少语句。

首先,在理解参数数值的类型前先来看看什么是基本类型和引用类型。

基本类型和引用类型

JavaScript中基本类型为简单类型:

  • string
  • number
  • boolean
  • undefined
  • null

值得注意的是其他多数语言引中string类型为用类型,而js中为基本类型。使用typeof null返回的是object。

引用类型为复合类型:

  • Date
  • Arry
  • Number
  • String
  • Boolean
  • Math
  • RegExp

还有两个核心类:

  • Object
  • Function

其中Number,String,Boolean为简单类型number,string,boolean的包装类型。

基本类型的变量和引用类型的变量最大区别在变量本身保存的值。基本类型的变量保存的就是数据本身,而引用类型的变量保存的是数据的引用,这个引用指向真实的数据地址。数据结构如图所示

基本类型在复制操作事将变量的值拷贝一份副本赋值给另一个变量,两个变量除了值相同之外无任何联系。

 

var num1 = 5;
var num2 = num1;
num2 ++;
alert(num1); //5
alert(num2); //6

num2的值不管怎么改变都不影响num1。

引用类型的变量的值是引用,指向数据本身。所以赋值的时候将引用赋值给另一个变量,两个变量指向同一个数据。所以改变一个内容另一个也跟着改变。

var person = new Object();
person.name = "landmine";
var person2 = person;
alert(person2.name);   //landmine
person2.name = "asd";
alert(person.name );     //asd

可以看到person2复制了person后对person2的name属性进行改变后,person的值也会改变。


参数传递

接下来进入重头戏,如何理解参数传递的都是以数值传递。通过上面的代码我们可以发现**引用类型的复制就是将本身的引用地址赋值给另一个变量**。这句话对于理解参数的传递很重要。第一次看js高程的时候由于忽略了这句话导致我一整个小节都看的半懂不懂。

首先是基本类型的参数传递:

var num = 10;
function fn(num2) {
    num2 +=10;
    return num2;
}
var num3 = fn(num);
alert(num);     //10
alert(num3);    //20

基本类型很好理解,参数以值类型传递进入函数内。复制的时候是复制值的副本,复制完后两个变量没有任何关联。

接下来是引用类型:

function fn(obj) {
    obj.name = "dilei";
}
var person = new Object();
person.name = "landmine";
fn(person);
alert(person.name);     //dilei

在我以前的理解中,按值传递就是将数据拷贝一份副本赋值给形参。这样不管是引用类型还是值类型,传递进函数后对形参进行修改数值都不会影响外部的变量。然而在上面的演示demo中可以看到,函数内修改数值会影响到函数外的变量。如今再次细读高程的这一小节后才发现,人家一开始就明明白白的写了

在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部

参考我之前的图片,参数传递的时候并不是将变量的数据拷贝一份副本赋值给形参。而是将变量的值拷贝一份副本赋值给形参。

从我上面的图片可以看出,基本类型的变量的数据和值是相同的,而应用类型的变量的值保存的是数据的引用,可以抽象对图片中的箭头。所以在参数传递的时候将按值传递给函数的形参,也就是把引用传递给函数的形参。

从上面的图片中可以看到,person和obj指向的是一个数据,所以可以通过修改obj来修改person的name属性。

也可以通过以下demo验证:

function fn(obj) {
    obj = {};
}
var person = new Object();
person.name = "landmine";
fn(person);
alert(person.name);     //landmine


上面的代码先将obj赋值一个空的object对象。如果是引用传递的话person会和object一样将会被重新赋值为一个空的object对象。但是参数的传递是值传递的,也就是说obj本身只不过是引用而已,重新赋值不过是将引用指向了另一块内存空间,原来的person以及person的值指向的内存空间的数据并没有被修改,所以person.name的值还是landmine。

 

posted @ 2016-04-25 10:48  地雷  阅读(1399)  评论(0编辑  收藏  举报