美文网首页
js函数中参数的传递

js函数中参数的传递

作者: 前端开发博客 | 来源:发表于2017-01-06 21:31 被阅读119次
   最近在读《javascript高级程序设计》时碰到了js传递方式的问题,花费了些时间,不过总算明白了。

数据类型
在 javascript 中数据类型可以分为两类:
基本类型值 primitive type,比如Undefined,Null,Boolean,Number,String。
引用类型值,也就是对象类型 Object type,比如Object,Array,Function,Date等。

变量的复制
众所周知,js中变量的基本类型和引用类型保存方式是不同的,这也就导致变量复制时也就不同了。如果从一个变量向另一个变量复制基本类型的值时,会将前者的值克隆一个,然后将克隆的值赋值到后者,因此这两个值是完全独立的,只是他们的value相同而已。
var num1 = 10;var num2 = num1;console.log(num2);//10

    上面的num1中被保存的值为10,当把num1的值赋值给num2时,num2的值也为10。但是这两个10是完全独立的,num2中的10只是被克隆出来的,相当于我写了一个word文档,把它放到了num1的文件夹中,然后我再复制这个word文档,就叫word副本吧,然后把这个副本放到num2的文件夹下,这两个word文档是完全一样的,修改任何一个都不会影响两一个。

num2 += 1;console.log(num1); //10console.log(num2); //11

     从上面可以看出修改num2的值,num1的值未发生变化。再来看下引用类型的复制。当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。
复制代码

var obj1 = { name : "111"};var obj2 = obj1;console.log(obj2.name); //111obj2.name = "222";console.log(obj1.name); //222


复制代码
    第一次打印出的结果为“111”,这个我们很容易理解,但是第二次打印出来的是“222”,有点莫名其妙了。这就是引用类型和基本类型的不同之处了。复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了。将obj1的值复制给obj2,而这个值的副本实际上是一个指针,这个指针指向存储在堆中的一个对象,也就是说创建了一个新的内存地址传给了obj2,obj1和obj2两个变量同时指向了同一个Object,当去改变这个对象时,他们的值都会改变,也就是说他们中任何一个作出的改变都会反映在另一个身上。下面的简易图可能更明了些。

函数参数的传递
《js高级程序设计》上是这样叙述参数传递的:所有函数的参数都是按值传递的,也就是说把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。所以如果能理解变量的复制,那么参数的传递也就很简单了。还是先从基本类型举例说明吧。


复制代码

var count = 10;function num(num1){ num1 = 1;return num1;}var result = num(count1);console.log(result);//1
console.log(count);//10,并未变成1

复制代码
  这个例子很容易理解,实际就是创建了一个count的副本,然后把count的值传入参数中,因为函数中定义了参数的值,所以1就将10覆盖了,最后的result返回1,而count并未发生变化。看一个有关传递对象的例子。
复制代码

var person = { name : "Tom"};function obj(peo){ peo.name = "Jerry";return peo;}var result = obj(person);console.log(result.name);// Jerryconsole.log(person.name);// Jerry


复制代码
   在上面的例子中,把person复制传入obj()中,peo和person指向了同一个对象,而在peo中修改了name属性,其实修改了它们共同指向的对象的name属性,相对应的外部person所引用的name属性也就改变了,所以打印出来的为Jerry。其实这个乍一看,感觉引用类型的参数是按照引用传递的,这就是我最初犯得错误。再来看一个例子。
复制代码

var person = { name : "Tom"}; function obj(peo){ peo = { name : "Jerry" }; return peo;}var result = obj(person);console.log(result.name);// Jerry
console.log(person.name);// Tom

复制代码
    上面的例子中,在函数中重新定义了一个对象,也就是现在堆内存中有两个对象,外部的person指向的是老的对象,被传入参数后指向的是新定义的对象,所以调用后返回的值是新定义的对象的值。如果是参数是按引用传递的,那么person.name打印出来的结果为Jerry,从这点可以得出参数是按值传递的(有的地方叫做按共享传递)。
 我们拿老罗推荐的《人类简史》把它形象化,描述的不太好。简史的第一章标题是“认知革命”,我们把它名字改为“person”根据后面的页码数可以直接找到“认知革命”的内容“也就是peoson所指向的对象”,第二章是“农业革命”,我们把它为“result”,其分目录有一节“记忆过载”(改名为“peo”),同样可以直接根据页码找到这一节内容。现在我们把“person”复制到“peo”中,第二章中的“peo”这一节就变成了“person”,而我们根据第一章中的“peoson”找到的还是第一章的内容,这是因为它们指向了不同的内容板块,互不干扰。在这里,堆内存就是每章的内容,而第一章和第二章内容是2个不同的对象,而这两者互不相干,因此打印外部person.name时,结果仍是以前的对象的属性值。

结论
总而言之,在js中参数都是按值传递的。我写例子粗糙了些,《javascript高级程序设计》中的例子描述的更清晰一些,更易理解。
http://www.cnblogs.com/open-wang/p/5208606.html

相关文章

  • js中的arguments对象

    《JavaScript高级程序设计》读书笔记 js中函数的参数与别的语言的参数有些不同。js中的函数不介意传递进来...

  • js函数中参数的传递

    数据类型在 javascript 中数据类型可以分为两类:基本类型值 primitive type,比如Undef...

  • JS中函数的参数

    参数不是必需的 在JS函数中,通常要通过参数来传递数据。但是JS和其他编程语言不一样的地方在于,JS并不在乎你传递...

  • 函数式编程

    Time: 20190716 函数式编程的概念在JS中随处可见。 函数可以作为函数的参数进行传递。 函数就是变量。...

  • 第二课 js类和对象

    函数 js中函数可以作为参数传递 第一种写法 上面代码是将say方法作为参数传递给execute方法 第二种写法 ...

  • js类和对象

    函数 js中函数可以作为参数传递 第一种写法 上面代码是将say方法作为参数传递给execute方法 第二种写法 ...

  • js类和对象

    函数 js中函数可以作为参数传递 上面代码是将say方法作为参数传递给execute方法 第二种写法 第三种写法 ...

  • 函数传参

    在JS中,函数可以接受任意数据类型的参数 函数可以返回值 函数的参数是按值传递,但是并不会改变函数的引用

  • 老董答疑总结(第二周)

    【课程相关】 sol代码里面函数参数是uint,js传递参数是负数的话,sol那边无法识别是否负数吧,如果js传递...

  • js类和对象

    函数 js中函数可以作为参数传递 回调函数 就是你调用别人(execute),然后别人会调用你(say),简言之:...

网友评论

      本文标题:js函数中参数的传递

      本文链接:https://www.haomeiwen.com/subject/czuxbttx.html