首页 > JS函数中对象的作用域的问题

JS函数中对象的作用域的问题

在《Javascript高级程序设计》中有个例子:

    function setName (obj) {
        obj.name = "Nic";
        obj = new Object();
        obj.name = "Gre";
    }
    var person = new Object();
    setName(person);
    alert(person.name); //"Nic"

这个我很不理解啊..主要不知道函数中的obj = new Object();这句话执行后对obj会有什么影响啊?obj之后指向哪里啊?


take it easy!
基本类型值传递,代码:
var a=5;
var b=a;
console.log(b)//5,这时在内存中有两个5。
引用类型值,代码:
var a={
saysomething:function(){
return "wahaha";
}
};
var b=a;
console.log(b.saysomething())//wahaha,这时在内存中只有一个对象,对象并没有被copy,copy的是指针,可以这么理解:就像你朋友和你朋友的哥们同时喜欢一个女孩,那啥都指向一个女孩。

再来说说什么是局部变量,在js权威指南是这么定义的:局部变量在函数体中的任何地方都是有定义的,参数变量也是局部变量。
再来看看你的代码,问题是:

function setName (obj) {

    obj.name = "Nic";
    obj = new Object();//为什么没有重新初始化person对象并重新添加属性。
    obj.name = "Gre";
}
var person = new Object();
setName(person);
alert(person.name); //"Nic"

因为obj是局部变量,所以这个过程就变得简单了,相当于这个:
var a={
myname:"尼古拉斯赵四"
};//把a当成person
var b=a;//把b当成obj,obj的指针指向person
b=new Object({myname:"郭达斯坦森"});//初始化obj,指向一个新对象,不关person什么事儿。
console.log(b.myname);//郭达斯坦森,
console.log(a.myname);//尼古拉斯赵四,person还是那个person。


这个和作用域没什么关系,这是关于JavaScript函数参数传递的问题。

由于参数是Object类型,是“copy of reference”,即对于参数内部值的修改影响外部值:

obj.name = "Nic"; // 会改变外部person本身。

所以,外部的person.name修改为"Nic"了。

而对于参数本身的修改不会影响外部值(相当于obj和person中间的线断了,再也连不上了)

obj = new Object(); // 这一步过后,内部的obj和外部的person就没有关系了。

如果这样:

 function setName (obj) {
    var tmp = obj;  //暂存obj
    
    obj.name = "Nic";
    obj = new Object();
    obj.name = "Gre";
    
    tmp.name = "John"; //修改
}
var person = new Object();
setName(person);
alert(person.name); // 此处就为“John”了

补充:对于原始类型,是“pass by value”,即修改参数不影响外部值。


js对基本类型是值传递, 对象则是共享传递。
共享传递意味着: 函数的参数是实参的引用副本, 比如你例子中setName方法的参数 obj, 所以当你obj = new... 的时候, obj的引用改变了, 但是由于它的引用是实参person的引用的副本, 所以并不会影响到实参person。


function setName (obj) {
    obj.name = "Nic";//[1]
    obj = new Object();//[2]
    obj.name = "Gre";//[3]
}
var person = new Object();
setName(person);//[4]
console.log(person.name); //"Nic"[5]

函数在执行时,函数参数是会声明为这个函数的动态变量~
JS中参数按"值"传递,对于基本类型number/string/boolean,复制其值给函数参数
对于对象类型,将对象的地址赋值给函数参数,这样函数参数变量和外部的对象都指向同一个地址
[1]obj和[4]person的变量指向同一个对象,其变量地址相同;添加了name属性
[2]执行后,obj指向发生变化,指向一个新的地址,一个新的对象,person函数指向原来的对象
[3]对新对象添加属性name
[5]person对象的name属性值为[1]语句赋值的结果,Nic

运行以下代码,能更清楚的看到其区别

function setName (obj) {
    obj.name = "Nic";//[1]
    obj = new Object();//[2]
    obj.name = "Gre";//[3]
    return obj;
}
var person = new Object();
var newObj=setName(person);//[4]
console.log(person.name); //"Nic"[5]
console.log(newObj.name); //"Gre"[6]
console.log(newObj===person);//false  newObj和person是2个不同的对象
【热门文章】
【热门文章】