今天做题的时候错了一道这样的题:
var foo = {n:1};
(function(foo){
var foo;
console.log(foo.n);
foo.n = 3;
foo = {n:2};
console.log(foo.n);
})(foo);
console.log(foo.n);
问:打印的结果
答案: 1 2 3
解析要点:
1. 变量的值——基本类型 与 引用类型
1.1 基本类型的值
- 基本类型的值就是例如字符串,数值,布尔值这样的值
比如var a = 1 - 它的值直接存在栈内存里(关于栈内存请戳→栈内存与堆内存)
- 变量间的赋值:
var a = 1
var b = 2
b = a
是直接把a对应的栈内存的值复制到b对应的栈内存里,覆盖掉原来的值。
1.2 引用类型的值
引用类型的值就例如:var c = {name:"xiaoc", age: 100}这种
- 它的存储形式是:在栈内存中存一个地址,该地址指向堆内存中保存的值
- 变量间的赋值
var c = {name:"xiaoc", age: 100}
var d = {name:"xiaod", age: 99}
d = c
它是直接把c对应的栈内存里的地址复制到d对应的栈内存里面,d以前的地址被覆盖,以前的地址对应的堆内存的内容,被垃圾回收机制清除掉
2. 变量的声明与赋值
var a = 1
var a
console.log(a) //打印出 1
重复声明而没有赋值的语句会被忽略
3. 函数中形参和局部变量同名
在函数内部,会把形参和局部变量同名直接视为变量的重复声明。和上面那种情况一样。不过函数的参数只在函数内部有效。
所以,套用到题目中:
var foo = {n:1};
(function(foo){
......
foo.n = 3; // 函数内部的foo的属性n的值被修改为3,因为地址相同,所以也就是修改了全局foo的属性n的值,变为3
......
})(foo); // foo的值被传进函数里(此时函数里的foo与全局的foo的栈内存里的地址相同)
console.log(foo.n); //打印出全局foo的n的值,全局的地址没有变,只是在函数内部被改为了3,所以打印出3
(function(foo){
......
foo.n = 3;
......
})(foo) //foo的值被传进函数里(此时函数里的foo与全局的foo的栈内存里的地址相同)
-
var foo: 函数内部变量的重复声明 无效 -
console.log(foo.n): 打印出接收到的参数的值, 为 1 -
foo.n = 3: 函数内部的foo的属性n的值被修改为3,因为地址相同,所以也就是修改了全局foo的属性n的值,变为3 -
foo = {n:2}: 函数内部的foo的地址被修改,指向一个新的堆内存空间,这里存的是{n:2} -
console.log(foo.n): 打印出函数内部的foo的n的值,因为在上一句已经被改地址了,所以是2 -
console.log(foo.n): 打印出全局foo的n的值,全局的地址没有变,只是在函数内部被改为了3,所以打印出3












网友评论