书上有个例子:
function setName(obj) {
obj.name = 'Nicholas';
obj = new Object();
obj.name = "Greg";
console.log(obj.name); // "Greg"
}
var person = new Object();
setName(person);
alert(person.name) // "Nicholas"
另外不传递参数改成:
function setName() {
person.name = 'Nicholas';
person = new Object();
person.name = "Greg";
console.log(person.name); // "Greg"
}
var person = new Object();
setName();
console.log(person.name) // "Greg"
分析一下原因:
第一个case:
person这个object作为参数传递给function的时候,function内部的作用域可以找到person而且这个时候obj的值是一个指向的是“堆内存空间中person所指向的这个Object它本身”(person本身也是个指针,obj是person这个指针被作为参数传递后复制出来的副本);然后下一步new出一个Object的时候,是在堆内存空间中新建了一个Object(),这个时候obj是指向这个新new出来的Object的指针,所以对这个Object新增一个叫name的属性并且在这个局部变量指针还未被销毁(即函数未执行完毕)之前打出log,输出的是这个新new出来的Object里的name属性,是Greg。需要注意的是,在function执行的这一个阶段里,对于原来的Object进行操作只有一次,即给它的name属性赋值为'Nicholas',随即在这个函数里就没有指针再指向它了,所以在外部的输出就是"Nicholas";
第二个case:
从始至终person伴随着我们的一直是person这个指针, 最初在声明阶段即在function外部那个 var person = new Object(); 时,这一步它是指向new出来位于堆内存内的Object。但在之后function中的执行阶段, person指针又被指向function里new出的这个Object了,注意这次不是局部变量,所以person就一直指向新的Object()了,所以后边的log输出就是这个新new出来的对象的name: "Greg" 。
所以第一个case里我想要让两个new出的Object里的name都输出出来,就可以建立一个全局变量,然后把指针的值存储区来,如下:
<span style="font-size:14px;">function setName(obj) {
obj.name = 'Nicholas';
obj = new Object();
obj.name = "Greg";
pointer = obj;
}
var person = new Object();
var pointer = null;
setName(person);
alert(pointer.name); // "Greg"
alert(person.name); // "Nicholas"</span>
好神奇啊啊啊啊啊啊啊!