javaScript 的值传递
我之前学习的是java,java 是按照引用传递的,当然如果是基本类型,是按照值传递的。
我们先看看java版本的:
public class Student {
private String name;
private int age;
public Student(String name,int age){
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student changeINfo(Student student){
student.name=student.getName()+"changed";
student.age=student.getAge()+100;
return student;
}
@Override
public String toString() {
return "Student{" + "name='" + name + '\'' + ", age=" + age + '}';
}
public static void main(String[] args) {
Student s1=new Student("张三",23);
System.out.println(s1);
s1.changeINfo(s1);
System.out.println(s1);
}
}
输出结果是这样的
Student{name=’张三’, age=23}
Student{name=’张三changed’, age=123}
这样就表示变量确实是改变了
也就是说java 是按照引用传递的(排除基本类型)。
接下来看看javaScript 下的效果好了。
var obj=new Object();
obj.name='zhang san';
function changeTest(obj) {
obj.name='李四';
}
alert('name:'+obj.name);//name:zhang san
changeTest(obj);
alert('name:'+obj.name);//name:李四
看到这个结果 大家一定觉得javascript 也是按照引用传递的是吧?
那么我改动一下你看看结果是什么:
var obj=new Object();
obj.name='zhang san';
function changeTest(obj) {
//obj.name='李四';
obj=new Object();
obj.name="王五";
}
alert('name:'+obj.name);//name:zhang san
changeTest(obj);
alert('name:'+obj.name);//name:zhang san
是的,你没看错,就是还是张三。
也就是说虽然我给传递过来的obj指定了新的对象 ,但是并没有我们预期原来的那样重新指向新的对象。
那么你就迷惑了吧?
这究竟是怎么回事?
上面的例子和之前的例子一样,只是这里面函数的变量名字我为了和原来的区分开了用了另外的b
大家现在看明白了吧,
js里面传递的不是引用 ,而是引用的引用 也就是说b是a的一个副本
所以 开始的时候b也是可以给obj1赋值的,也就是我们以为是按照引用传递的原因,
但是呢,我们后来b重新指向了另外的对象,obj2,
而 a还是指向的obj1。
而这个obj2还是个 短命鬼,方法结束了就基本挂了。
其实也没有什么意义了。
这就是其特殊的地方。
按共享传递 call by sharing
准确的说,JS中的基本类型按值传递,对象类型按共享传递的(call by sharing,也叫按对象传递、按对象共享传递)。最早由Barbara Liskov. 在1974年的GLU语言中提出。该求值策略被用于Python、Java、Ruby、JS等多种语言。
该策略的重点是:调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)。 它和按引用传递的不同在于:在共享传递中对函数形参的赋值,不会影响实参的值。如下面例子中,不可以通过修改形参o的值,来修改obj的值。