全局对象充当顶级词汇环境(范围链的顶部,如果你愿意的话)。这意味着可以通过直接引用(如变量)访问全局属性:
// global code
this.foo = 1; // creating a global property
foo // accessing the global property via a direct reference
这也意味着可以通过属性引用访问全局变量:
// global code
var foo = 1; // creating a global variable
this.foo // accessing the global variable via a property reference
现在,根据上述信息,似乎可以互换地使用术语“全局变量”和“全局属性”,这意味着术语代表完全相同的全局绑定集< / strong>即可。
但是,使用var
创建的全局变量之间存在两个差异,例如。 var foo = 1;
,以及通过作业创建的全局属性,例如this.foo = 1;
:
全局变量静态范围,而全局属性动态添加到全局环境:
foo // => undefined
bar // throws ReferenceError
var foo = 1;
this.bar = 1;
因此,在程序评估之前,全局变量绑定,而在评估赋值时,在程序评估期间绑定全局属性。
全局变量是不可配置的,即它们不能被删除(更具体地说,它们的相应绑定随后不能从环境中删除),而通过赋值创建的全局属性是可配置的。
// the names "foo" and "bar" are bound to the global environment
var foo = 1;
this.bar = 1;
// the binding "bar" can be removed from the global environment subsequently
delete this.bar;
// the binding "foo" cannot be removed subsequently
话虽这么说,但应该注意,可以创建不可配置的全局属性:
Object.defineProperty( this, 'bar', { value: 1 }); // non-configurable by default
现在,根据这些新信息,可以说只有静态范围的全局绑定可以称为全局属性和全局变量,而动态添加的全局绑定只是全局属性,而不是全局变量,这意味着术语“全局变量”表示由术语“全局属性”表示的集合的子集,如:
所有全局变量都是全局属性
只有静态范围的全局属性是全局变量
那么,哪种解释是正确的?这两个术语是代表同一组绑定,还是一个是另一个的子集?
我理解术语“全局属性” - 全局属性是全局对象的属性。但是,术语“全局变量”似乎含糊不清。有些人将它用作“全局属性”的同义词,而其他人则将其定义为通过var
语句定义的全局属性。我的问题的目的是确定这两个含义中的哪一个是正确的
答案 0 :(得分:5)
嗯,你已经知道我要说的所有内容,以区分变量和附加到window
的属性的边缘情况。
如果您想变得非常,非常迂腐,我想您可以将全局范围视为功能范围和范围,其中window
对象已扩展使用与程序中提供的相同的隐藏配置设置的属性(例如:vars可以重新分配但不能删除)。所以从这个意义上讲,就功能而言,它们是不同的,并且反映了属性和变量的属性,全局范围。
并指出它们是完全没问题的
但是那里的大多数人甚至没有认识到这种差异,更不用说区分这两个术语了
即使是那些重要的JS作者也提到了通过省略global variable
而意外地设置var
,实际上,JS会扩展函数范围,如果它在没有命名的情况下使其进入全局范围,它会附加global property
个数据,而不是global variable
。
但这真的让我们感到难关 - 一个强大,稳定和可靠的JS应用程序,与其他应用程序一起生活在现代网页上,真的不应该过分关注这些差异。
在这种情况下,目标是尽可能少地使用全局属性和变量。
此外,变量/属性碰撞的危险是相同的,无论它是什么
变量不受delete
的影响,但是任何有用的程序有可能delete
一个甚至从未设置的属性?
所以个人而言,我认为理解边缘情况是件好事,但我也认为虽然我内心的学生想要同意存在差异,而且他们并不是很狡猾,但我的实用主义者不寒而栗地想到了人们积极利用全球范围的世界,这对他们产生很大的影响。
答案 1 :(得分:2)
可以找到一个很好的解释here,但我会缩短它来回答你的问题。当你说:
这两个术语代表完全相同的全局绑定集。
......你几乎是正确的,但并不完全正确。像this.foo = 1
这样的属性分配会保存到全局对象中。然而,var bar = 2
等变量声明会保存到变量对象中。
在全局范围内执行时,全局对象和变量对象都由同一个对象 - 全局对象表示(当您在浏览器中执行时,这是{{ 1}} object)。
我提到这一点是因为你的解释不足以解释这个程序的行为:
window
但这并不意味着全局属性和全局变量是相同的。所有属性都有三个隐藏的标记:// "this" refers to the global object. But global object is also acting as the
// variable object! Because of that, the following code works:
var foo = 1;
alert(this.foo); // 1
(function() {
// "this" still refers to the global object! But the *variable* object has
// changed because we're now in the execution context of a function, thus
// the behavior changes:
var bar = 2;
alert(this.foo); // 1
alert(this.bar); // undefined
})();
,ReadOnly
和DontEnum
。
使用DontDelete
等隐式属性声明时,this.foo = 1
属性设置为DontDelete
。当您使用false
之类的变量声明时,var bar = 2
属性设置为DontDelete
,从而表示使用true
运算符时它们之间的差异。
回答你的改写问题:
[T]他的术语“全局变量”似乎含糊不清。有些人用它作为 “全球财产”的同义词,而其他人则将其定义为全球性 已通过var语句定义的属性。我的意图 问题是确定这两个含义中的哪一个是正确的。
这个词没有明确定义,因此你只要求一个意见。
通常,使用语法delete
创建变量时使用术语“全局属性”,使用语法this.foo = 1
创建变量时使用术语“全局变量” 。没有什么可以讨论的。
这两个词都没有对幕后发生的事情产生真正的影响,因此你能做的最好的事情就是了解你已经完成的幕后实际情况。
进一步要求对两个任意条款的绝对定义只会让你成为一个不受欢迎的人。