From 347152fe2dd20f365a868526a7c85b17402b1b94 Mon Sep 17 00:00:00 2001 From: ok8 Date: Sun, 5 Jul 2015 22:53:17 +0300 Subject: [PATCH] =?UTF-8?q?=E5=BB=BA=E8=AE=AE=E6=9B=B4=E5=90=88=E7=90=86?= =?UTF-8?q?=20javascript=20by=20reference=20vs=20by=20value=20=E7=9A=84?= =?UTF-8?q?=E8=A7=A3=E9=87=8A=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- grammar/function.md | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/grammar/function.md b/grammar/function.md index e63a1794..cb437a0a 100644 --- a/grammar/function.md +++ b/grammar/function.md @@ -530,7 +530,7 @@ f(0) // 0 ### 传递方式 -JavaScript的函数参数传递方式是传值传递(passes by value),这意味着,在函数体内修改参数值,不会影响到函数外部。 +JavaScript的参数传递方式是全部都是“传值传递”(passes by value),只不过当一个变量指向对象(包括数组)时,该“变量”其中的“值”即为该对象的引用,当变量中的值为某对象引用时,改变该“变量”的“值”时,并不会影响其所指向对象本身以及其中的值,而是仅仅指向另一个引用或者被替换成其他值。然而,当你利用被传入的变量改变其所指向对象中的属性或者方法时,那么即时在函数内部,该变量也将会改变函数外部对象中属性或方法的值,因为该变量的值为函数外对象的引用,我们通过该引用访问了其中的属性或方法,并且修改了它。 {% highlight javascript %} @@ -547,45 +547,27 @@ p // 2 // 修改复合类型的参数值 var o = [1,2,3]; -function f(o){ - o = [2,3,4]; +function f(o){ // 这里o变量有其自己的内存地址,只不过里面的值存储了和函数外部o相同的引用到数组[1,2,3] + o = [2,3,4]; // 这时函数内部的o变量被存储了新的引用,即为数组[2,3,4]的地址, 注意:这里我们丝毫没有改变原数组[1,2,3],只是覆盖了一个新变量而已,但函数外部的o依然指向[1,2,3],所以值不会变 + console.log(o); // [2,3,4] } f(o); o // [1, 2, 3] -{% endhighlight %} - -上面代码分成两段,分别修改原始类型的参数值和复合类型的参数值。两种情况下,函数内部修改参数值,都不会影响到函数外部。 - -需要十分注意的是,虽然参数本身是传值传递,但是对于复合类型的变量来说,属性值是传址传递(pass by reference),也就是说,属性值是通过地址读取的。所以在函数体内修改复合类型变量的属性值,会影响到函数外部。 - -{% highlight javascript %} - -// 修改对象的属性值 -var o = { p:1 }; +// 修改复合类型其中的属性 -function f(obj){ - obj.p = 2; -} - -f(o); -o.p // 2 +var q = [1,2,3]; -// 修改数组的属性值 -var a = [1,2,3]; - -function f(a){ - a[0]=4; +function changQ(cq) { + cq[0] = 5; // 我们通过cq变量中的引用访问到[1,2,3]的地址,并且改变其中的值,注意这次,我们通过传进来的“值”(数组q的地址)访问并且改变了q数组,由于函数外q变量所指向的也是该数组,所以也改变了函数外部q的值,因此看似好像达到了按址传递的效果,其实cq变量有其自己的内存地址,只是其“值”存储了复合类型的引用 } -f(a); -a // [4,2,3] +changQ(q); +q // [5, 2, 3] {% endhighlight %} -上面代码在函数体内,分别修改对象和数组的属性值,结果都影响到了函数外部,这证明复合类型变量的属性值是传址传递。 - 某些情况下,如果需要对某个变量达到传址传递的效果,可以将它写成全局对象的属性。 {% highlight javascript %}