84669 人が学習中
152542 人が学習中
20005 人が学習中
5487 人が学習中
7821 人が学習中
359900 人が学習中
3350 人が学習中
180660 人が学習中
48569 人が学習中
18603 人が学習中
40936 人が学習中
1549 人が学習中
1183 人が学習中
32909 人が学習中
JavaScript中函数的参数传递方式都是按值传递,没有按引用传递,应该怎么理解??
“能不能举个例子”
补充:保存引用的对象(比如数组,它是按照引用传递的又该怎么理解)
function add(arr,num){ for(var i=0; i<arr.length; i++){ arr[i]+= num; } } var arr1 =[1,2,3,4,5]; add(arr1,5); console.log(arr1);//[6, 7, 8, 9, 10]
认证0级讲师
楼上的回答中,@kikong 的回答是最靠谱的。
当传递原始类型值给形参时,传递的就是原始值本身。当传递引用类型值给形参时,传递的是一个指针(一个特殊的值)。
这就是所谓的 JS 中的按值传递。
其实吧,JavaScript 的参数传递涉及两组核心概念:
按值传递和按共享传递(call by value VS call by sharing)
call by value
call by sharing
重新绑定和变异 (rebinding VS mutation)
rebinding
mutation
参数传递的本质其实是一个隐式赋值,赋值运算(=)发生了什么,参数传递就发生了什么。
var num1 = 5 var num = num1
num1 保存着数字类型值 5,将 num 赋值为 num1,num就保存了数字 5。这是按值传递。
num1
5
num
var arr1 = [1, 2, 3, 4, 5] var arr = arr1
arr1 保存一个引用类型值,也可以理解为 arr1 指向数组 [1, 2, 3, 4, 5]的内存地址。将 arr 赋值为 arr1, arr 也就指向了该数组的内存地址。这是按共享传递(两个变量共享该对象的内存地址)。
arr1
arr
var arr1 = [1, 2, 3, 4, 5] var arr = arr1 arr = [2, 3, 4, 5, 6]
arr 原本与 arr1 一起指向数组 [1, 2, 3, 4, 5] 的内存地址,但通过另一个赋值语句,使 arr 重新指向了数组 [2, 3, 4, 5, 6] 的内存地址。这是重新绑定。
var arr1 = [1, 2, 3, 4, 5] var arr = arr1 arr1.push(6) console.log(arr1.length) // => 6 console.log(arr.length) // => 6
任何对 arr1 或 arr 的修改都是对其所指向对象的修改。这是 mutation。
这里尤其需要注意的是 rebinding。对 arr 重新赋值之后,arr1 与 arr 已经指向了不同的内存地址,两者已经断开联系。
在你的例子中,
在执行 add(arr1, 5) 时,传参完成的是隐式的赋值操作(即,arr = arr1, num = 5),其中传参给 arr 是 按共享传递,传参给 num 是按值传递
add(arr1, 5)
arr = arr1, num = 5
在函数体内修改 arr (arr[i] += num),是 mutation 操作,所以即便 arr 在随后被销毁了,通过 arr1 也能观察到变更。
arr[i] += num
javascript中的参数传递都采用 按值传递的方式 对于对象来说,这个值是指对象的内存地址 对基本类型,这个值是原始值
=======
function add(arr,num){ console.log(arr);//[1,2,3,4,5]; //arr被重新赋值前和arr1的相同 arr=[5,6,7,8,9];//arr被重新赋值,指向的地址不同,但不会影响arr1的指向,也就是其地址信息 for(var i=0; i<arr.length; i++){ arr[i]+= num; } console.log(arr);//[10, 11, 12, 13, 14] } var arr1 =[1,2,3,4,5]; add(arr1,5); console.log(arr1);//[1, 2, 3, 4, 5]
1、按值传递: 按值传递就是将变量先复制一份,然后将复制的变量传入函数,如下面函数,先将num复制,然后再将复制的值传入add函数,执行下面函数就很明了了。 var num=10; function add(num){ num+=10; return num; } console.log("这是add方法返回的值 "+add(num));//这是add方法返回的值 20 console.log("这是原始的num "+num);//这是原始的num 10 2、按引用传递 按引用传递思想和按值传递一样,先将对象的引用复制一份,然后再将所复制的引用传入函数;不同的是,这两个引用都指向同一个对象。来看一下面的一段代码: function person(){ this.name="小明"; this.age=23; } p1=new person(); p2=new person(); function editName(person){ person.name="小红"; } console.log(p1.name);//小明 editName(p1); console.log(p1.name);//小红 注意:不是说可以改变对象的值就是说明是按引用传递,例如以下代码: function chengeName(p){ p=new person(); p.name="小小"; } p2=new person(); console.log(p2.name);//小明 chengeName(p2); console.log(p2.name);//小明 这里p2的name虽然没有改变,但它也是属于按引用传递的
js中函数参数都是按值传递的,即使函数局部改变引起了全局的改变。javascript高级程序设计里是这么说的,可是js里对象哪里有值传递啊。。。直接传值的话,又哪来的深复制浅复制啊。搞不懂了function setName(obj) {obj.name = 'obj';obj = new Object();obj.name = 'obj2';}
var person = new Object();setName(person);console.log(person.name);//obj
http://www.zhihu.com/question/27114726http://www.zhihu.com/question/25336993
传递参数:所有函数的参数都是按值传递的。基本类型值的传递如同基本类型变量的复制,而引用类型值的传递,如同引用类型变量的复制。
复制变量值:基础类型会创建一个新值,把值复制到新位置,之后彼此独立。引用类型会复制指针,新老变量(复制和被复制的变量)引用同一个对象,改变其中一个,就会影响另一个。
例子可以参考js高级程序设计第三版4.1.3
把引用类型的变量想成一堆指针,就是全按值传递。
var foo = { bar: function() { return this.baz; }, baz: 1 }; (function(){ return typeof arguments[0]();//"undefined" })(foo.bar);
你看这个例子,如果是传递引用,那么foo.bar应该会被当作函数传进去,后面的typeof就不会是undefined了。对吧。
楼上的回答中,@kikong 的回答是最靠谱的。
当传递原始类型值给形参时,传递的就是原始值本身。
当传递引用类型值给形参时,传递的是一个指针(一个特殊的值)。
这就是所谓的 JS 中的按值传递。
其实吧,JavaScript 的参数传递涉及两组核心概念:
按值传递和按共享传递(
call by value
VScall by sharing
)重新绑定和变异 (
rebinding
VSmutation
)参数传递的本质其实是一个隐式赋值,赋值运算(=)发生了什么,参数传递就发生了什么。
num1
保存着数字类型值5
,将num
赋值为num1
,num
就保存了数字 5。这是按值传递。arr1
保存一个引用类型值,也可以理解为arr1
指向数组 [1, 2, 3, 4, 5]的内存地址。将arr
赋值为arr1
,arr
也就指向了该数组的内存地址。这是按共享传递(两个变量共享该对象的内存地址)。arr
原本与arr1
一起指向数组 [1, 2, 3, 4, 5] 的内存地址,但通过另一个赋值语句,使arr
重新指向了数组 [2, 3, 4, 5, 6] 的内存地址。这是重新绑定。任何对
arr1
或arr
的修改都是对其所指向对象的修改。这是 mutation。这里尤其需要注意的是 rebinding。对
arr
重新赋值之后,arr1
与arr
已经指向了不同的内存地址,两者已经断开联系。在你的例子中,
在执行
add(arr1, 5)
时,传参完成的是隐式的赋值操作(即,arr = arr1, num = 5
),其中传参给arr
是 按共享传递,传参给num
是按值传递在函数体内修改 arr (
arr[i] += num
),是mutation
操作,所以即便arr
在随后被销毁了,通过arr1
也能观察到变更。javascript中的参数传递都采用 按值传递的方式
对于对象来说,这个值是指对象的内存地址
对基本类型,这个值是原始值
=======
1、按值传递:
按值传递就是将变量先复制一份,然后将复制的变量传入函数,如下面函数,先将num复制,然后再将复制的值传入add函数,执行下面函数就很明了了。
var num=10;
function add(num){
num+=10;
return num;
}
console.log("这是add方法返回的值 "+add(num));//这是add方法返回的值 20
console.log("这是原始的num "+num);//这是原始的num 10
2、按引用传递
按引用传递思想和按值传递一样,先将对象的引用复制一份,然后再将所复制的引用传入函数;不同的是,这两个引用都指向同一个对象。来看一下面的一段代码:
function person(){
this.name="小明";
this.age=23;
}
p1=new person();
p2=new person();
function editName(person){
person.name="小红";
}
console.log(p1.name);//小明
editName(p1);
console.log(p1.name);//小红
注意:不是说可以改变对象的值就是说明是按引用传递,例如以下代码:
function chengeName(p){
p=new person();
p.name="小小";
}
p2=new person();
console.log(p2.name);//小明
chengeName(p2);
console.log(p2.name);//小明
这里p2的name虽然没有改变,但它也是属于按引用传递的
js中函数参数都是按值传递的,即使函数局部改变引起了全局的改变。javascript高级程序设计里是这么说的,可是js里对象哪里有值传递啊。。。
直接传值的话,又哪来的深复制浅复制啊。搞不懂了
function setName(obj) {
obj.name = 'obj';
obj = new Object();
obj.name = 'obj2';
}
var person = new Object();
setName(person);
console.log(person.name);//obj
http://www.zhihu.com/question/27114726
http://www.zhihu.com/question/25336993
传递参数:所有函数的参数都是按值传递的。基本类型值的传递如同基本类型变量的复制,而引用类型值的传递,如同引用类型变量的复制。
复制变量值:基础类型会创建一个新值,把值复制到新位置,之后彼此独立。引用类型会复制指针,新老变量(复制和被复制的变量)引用同一个对象,改变其中一个,就会影响另一个。
例子可以参考js高级程序设计第三版4.1.3
把引用类型的变量想成一堆指针,就是全按值传递。
你看这个例子,如果是传递引用,那么foo.bar应该会被当作函数传进去,后面的typeof就不会是undefined了。对吧。