如果全局上下文中的变量是属性,那么为了闭包的目的,如何区分它们
If variables in the global context are properties, then how are they distinguished for the purposes of closures?
如果全局上下文中的变量是属性(在全局上下文上),那么为了闭包的目的,如何将它们与全局上下文上的其他属性区分开来?
显然这不起作用:
function foo() {
this.a = 'a';
this.bar = function() { console.log(a); }
}
new foo().bar(); // ReferenceError: a is not defined
显然,这确实有效:
var a = 'a';
function bar() {
console.log(a);
}
bar(); // a
但如何给定变量a
是一个"属性"。我的误解在哪里?
它们是不可区分的——它们只是一个变量和一个属性。您可以想象全局作用域是唯一可以作为实际语言对象访问的作用域对象。
全局环境由绑定到全局对象的环境记录(如with
语句)组成,全局对象本身在浏览器中显示为window
对象。
使用构造函数示例:
function Foo() {
with (this) {
this.a = 'a';
this.bar = function() { console.log(a); }
// Is `a` a variable or a property? It's *one* thing, available as both.
}
}
new Foo().bar(); // 'a'
全局作用域是Web浏览器中的window
对象。因此,全局范围中的变量声明成为window
的属性。
// Somewhere in the global scope...
// Both declarations add a property to window
window.a = "hello world";
var a = "hello world";
另一方面,当使用this
关键字将属性添加到对象时,并不是将其添加到内置的window
对象中。这就是为什么闭包不会将this.a
定位为a
。
如果您不使用this
限定属性名称,则它是一个可以是局部或全局的变量-将全局理解为window
对象的属性-。
JavaScript运行时在其当前范围内查找变量,否则在父范围内查找,依此类推,直到它到达全局范围,如果window
不拥有属性(实际上是变量标识符),则浏览器或任何JavaScript运行时将确定该变量为未定义的。
在第一个示例中,this.a
的作用域是foo
的this
上下文。如果您将代码更改为:
function foo() {
var a = 'a';
this.bar = function() { console.log(a); }
}
new foo().bar();
它会起作用的。否则你必须这样做:
function foo() {
this.a = 'a';
this.bar = function() { console.log(this.a); }
}
new foo().bar();
第一个代码示例不起作用的原因是:
console.log(a);
正在bar()
方法的范围中查找名为a
的变量。但您从未声明过这样的变量。您只在名称为a
的其他对象上声明了一个属性。如果你想引用该属性,你必须使用合适的对象引用,如下所示:
console.log(this.a);
Javascript中的所有属性都必须包括该属性所在的对象才能访问它们,全局对象上被视为全局变量的属性除外。因此,在您的上下文中,a
与this.a
不是一回事。
只有在全局作用域中声明变量或显式附加到全局对象(在浏览器中为window
),或者在没有声明的情况下隐式分配变量,并且您不处于严格模式下(我称这些意外的全局变量为可怕的事情),变量才是全局的。
所以,这里有几件事你可以做。
使用公共实例变量:
function foo() {
this.a = 'a';
this.bar = function() { console.log(this.a); }
}
new foo().bar(); // outputs the member variable a
或者使用构造函数局部变量(本质上是私有实例变量):
function foo() {
var a = 'a';
this.bar = function() { console.log(a); }
}
new foo().bar(); // outputs the member variable a
或者使用实际的全局(不推荐):
var a;
function foo() {
a = 'a';
this.bar = function() { console.log(a); }
}
new foo().bar(); // outputs the global a
- 在underscorejs模板中使用闭包
- setTimeout可以与闭包内的函数一起使用吗
- 附加到原型属性的Do函数没有闭包
- 使用闭包共享构造函数参数
- 使用Google闭包编译器包含一个Ecmascript 6类
- 从js引擎的角度来看闭包和构造函数是如何工作的
- for循环中的JavaScript闭包
- Javascript闭包-如何防止内存泄漏
- 子类访问父类's闭包变量
- 闭包如何具体化数据封装
- Javascript.闭包和dynamic'这'实际上具有约束力
- 构造函数函数闭包变量
- 闭包js框架-将ArrayBuffer转换为字符串
- 如何在Angularjs中重构闭包中的重复代码
- 如何告诉闭包javascript编译器不要混淆webkitAudioContext的方法名称
- Google闭包和生成的getters/ssetter
- 如何冻结函数's在闭包中的变量
- 如何使用外部Javascript库(如jQuery)重命名Google闭包样式表
- 使变量可用于不带闭包的异步调用
- 什么'这个javascript闭包的区别是什么