我阅读了David Mark关于js框架"Sencha"的以下分析:https://gist.github.com/3279190在那里他说。。。
他们想要的是一个全局变量,但最终得到的是全局对象的一个属性。根据规范和(以及实施历史),两者之间有足够的差异,需要注意不要混淆它们(正如这里所做的那样)。
但据我所知,var my_global = 123;
和(在浏览器环境中)window.my_global = 123;
之间没有任何区别(在那个例子中,我假设环境是浏览器,因此使用了window
,但我本可以只使用this.my_global
,因为在不同的环境中运行时,全局对象显然会不同)。
但是忽略这个微小的差异,将属性分配给全局对象和创建全局变量之间有区别吗?我不这么认为,创建全局变量只是将属性分配给全局对象的另一种方式。
我相信在一些浏览器中可能会出现问题,如果它们有一个id为"my_global"的元素,那么显然这会导致JavaScript引用正确内容的问题,但我不确定这个问题是如何/是什么原因造成的(例如,将属性分配给全局对象会导致元素id问题发生吗,还是它声明了一个全局变量会导致元素id问题?)
有人能帮我澄清一下吗?
更新,2020年4月
正如D.Pardal在评论中所指出的,下面写在2012年的第一句话在支持ES模块(规范)的环境中不再总是正确的。在ES模块中,var
语句不会生成全局对象的属性。
原始答案
在全局作用域中使用var
创建的变量确实会创建全局对象的属性。但是,此属性与尚未使用var
创建的全局对象的属性具有不同的行为。
首先,变量声明的执行方式存在差异:全局作用域中的var
语句在执行任何代码之前都会创建全局对象的属性,这种效果通常被称为提升,在web上有很好的记录(请参阅下面的参考资料)。
其次,与未使用var
创建的全局对象的属性不同,全局变量不能使用delete
运算符删除(尽管在旧版本的IE中不是这样)。delete
不能用于删除变量。这种差异源于每个对象属性所具有的内部属性属性。这些属性在ECMAScript规范中指定。在ECMAScript 5术语中,var foo = "bar"
使用[[Configurable]]
属性false
创建全局对象的属性foo
,而this.foo = "bar"
(在全局范围中)使用[[Configurable]]
属性true
创建foo
属性。
参考文献:
-
德米特里·索什尼科夫(Dmitry Soshnikov)在他的优秀著作中详细地写到了这一点系列文章,ECMAScript 262-3详细介绍。我推荐阅读第2章的全部内容,但最相关的部分称为关于变量。
-
前面链接的kangax文章包含了很多浏览器错误和偏差的相关信息和细节,再加上关于CCD_ 20的其他怪癖。
-
Angus Croll的Variables vs.Properties in JavaScript文章,链接到许多与此答案相同的资源。
-
规格:ECMAScript 5.1。
我不知道有任何实际的区别,但引用为global或window.var肯定有一些区别。一个简单的例子:
'use_strict';
console.info(window.foo);
console.info(foo);
window.foo只会返回undefined。foo将给出undefined作为错误。所以是的,它们是不同的。但是在好的代码中(我的例子是非常糟糕的代码)看起来并没有什么区别。(但如果有的话,我真的很想了解更多:)
var count = 123
var global_object = {
count:var = 456
console.log(this.count) //returns 456
}
console.log(count) //returns 123
console.log(global_object) //returns 456
上面,count首先被定义为一个全局变量。然后,它被定义为全局对象中的一个属性。全局对象中的定义是该对象的本地定义。
我现在发现我的答案有一个问题,当我第一次发布这个时我没有想到。在上面投票最多的答案中,我注意到它正确地表明,在问题中的全局变量的情况下,在其定义中使用了"var",但在全局对象的情况下没有使用"var"。我仍然希望范围在这里发挥作用(它将在ActionScript中发挥作用)。
我对上面的例子还有其他几个问题。count:var=对我来说是错误的。也许应该是var count=456。然而我仍然希望在函数中声明的变量只在该函数中具有作用域。因此,示例中的console.log表达式应该为true。