var s1 = "sharpxiajun";
var s2 = s1;
console.log(s1); 运行结果:sharpxiajun
console.log(s2); 运行结果:sharpxiajun
s2 = "xtq";
console.log(s1); 运行结果:sharpxiajun
console.log(s2); 运行结果:xtq
上面是基本类型变量的赋值,我们再看看下面的代码:
var obj1 = new Object();
obj1.name = "obj1 name";
console.log(obj1.name);// 运行结果:obj1 name
var obj2 = obj1;
console.log(obj2.name);// 运行结果:obj1 name
obj1.name = "sharpxiajun";
console.log(obj2.name);// 运行结果:sharpxiajun
上面为引用类型变量的赋值
我们发现当复制的是对象,那么obj1和obj2两个对象被串联起来了,obj1变量里的属性被改变时候,obj2的属性也被修改。
函数传递参数的本质就是外部的变量复制到函数参数的变量里,我们看看下面的代码:
function testFtn(sNm,pObj){
console.log(sNm);// 运行结果:new Name
console.log(pObj.oName);// 运行结果:new obj
sNm = "change name";
pObj.oName = "change obj";
}
var sNm = "new Name";
var pObj = {oName:"new obj"};
testFtn(sNm,pObj);
console.log(sNm);// 运行结果:new Name
console.log(pObj.oName);// 运行结果:change obj
这个结果和变量赋值的结果是一致的。
在javascript里传递参数是按值传递的。
上面函数传参的问题是很多公司都爱面试的问题,其实很多人都不知道javascript传参的本质是怎样的,如果把上面传参的例子改的复杂点,很多朋友都会栽倒到这个面试题下。
为了说明这个问题的原理,拿两张图举例,如下所示:
这是基本类型存储的内存结构。
这是引用类型存储的内存结构。
还有个知识,如下:
在javascript里变量的存储包含三个部分:
部分一:栈区的变量标示符;
部分二:栈区变量的值;
部分三:堆区存储的对象。
在javascript里变量的复制(函数传参也是变量赋值)本质是传值,这个值就是栈区的值,而基本类型的内容是存放在栈区的值里,所以复制基本变量后,两个变量是独立的互不影响,但是当复制的是引用类型时候,复制操作还是复制栈区的值,但是这个时候值是堆区对象的地址,因为javascript语言是不允许操作堆内存,因此堆内存的变量并没有被复制,所以复制引用对象复制的值就是堆内存的地址,而复制双方的两个变量使用的对象是相同的,因此复制的变量其中一个修改了对象,另一个变量也会受到影响。