Javascript
中变量可以存放两种类型的值,一种为原始值(primitive value
),如 Undefined, Null, Boolean, Number, String
。这类值存放在栈内部,每赋值一次就创建一个新的拷贝。另一种为引用值(reference value)
,这类值存在堆内存中,只能通过引用赋值。举例说明:
- var a = 'test';//原始值
- var b = function() {}; //引用值
- var a = 'test';//原始值
- var b = function() {}; //引用值
- b.a = 'test';
- function change(m, n) {
- m = 'change';
- n.a = 'change';
- }
- change(a, b);
a
仍然是
test
,但是 变量
b
的属性
a
的值则已经为
change
,这也就是说前者相当于是拷贝了一份值,而后者则是引用赋值。
而闭包问题我是这样理解的,因为
Javascript
只有两种作用域,一是全局作用域,二是函数作用域,它是没有块级作用域的。所以闭包的出现就相当于利用一个匿名函数的壳模拟出一个块级作用域。举个更明显的闭包例子:
- for(var i = 0; i < 10; i++) {
- (function(e) {
- setTimeout(function() {
- console.log(e);
- }, 1000);
- })(i);
- }
连着上面的知识,这里往匿名函数内部传的参数将会被拷贝一份,也就是说循环没执行一次就拷贝变量
i
的值到匿名函数内部。
这里如果没有闭包的话:
- for(var i = 0; i < 10; i++) {
- setTimeout(function() {
- console.log(i);
- }, 1000);
- }
由于变量
i
直接暴露在全局作用域内,当调用
console.log
函数开始输出时,这是循环已经结束,所以会输出10个10。
这是我对题主问题的理解,希望能对题主有帮助,可能还有不完善的地方,我打算写篇博文好好总结下。