一场由变量赋值所引发的血案
**血案背景:**公司项目中引用了mod.js来对模块加载和管理,当出现模块循环引用的时候遇到了,模块js之前已经加载过,但取不到模块数据的情况,最后确定了问题是由于对象的赋值所导致的(情况可以参照下面的例4)。
变量的赋值很基础,但是也难免有时候犯糊涂,可以先看以下几个例子:
例1
var man = 'tian';
var man2 = man;
man='yuan';
console.log(man2);
console.log(man);
输出: tian、yuan
例2
var man = {};
var man2 = man;
man={name:3};
console.log(man2.name);
console.log(man.name);
输出: undefined、3
例3
var man = {};
var man2 = man;
man.name=33;
console.log(man2.name);
console.log(man.name)
输出: 33、33
例4
var man = {export:{}};
var ept=man.export;
var man2 = man;
man2.export={a:333222};
console.log(ept);
console.log(man.export);
console.log(man2.export);
输出: {}、{a: 333222}、{a: 333222}
归结一下就是基本类型是按照值来访问的,引用类型是按照址来访问的。
基本类型(undefined,boolean,number,string,null)变量存储在栈中,赋值时使用的就是变量对的实际值,像例1一样,赋值后两个变量值传递后就没有关系了,互相不影响。
引用类型(Object)的变量数据实际存储在堆中,并在栈中保存变量名以指向变量在堆中的实际地址(可以把引用类型的变量看作一个指向实际存储地址的指针)。当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在堆中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。可以参照后面三个例子,其中例2和例4的引用地址有改变需注意。