我正在学习JavaScript中的提升。当我尝试这个代码
console.log('name', name)
console.log('age', age)
console.log('occupation', occupation)
var name = 'tom'
var age = '23'
var occupation = 'builder'
在我的chrome开发工具中,我得到了
name tom
age undefined
occupation undefined
为什么名称不是未定义的,而其他变量是未定义的?
编辑:
我的html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src = "index.js"></script>
</body>
</html>
我的index.js文件
console.log('name', name)
console.log('age', age)
console.log('occupation', occupation)
var name = 'tom'
var age = '23'
var occupation = 'builder'
我重新启动了电脑,创建了新文件,但一切都没有改变。在firefox中,我得到
name <empty string>
age undefined
occupation undefined
这正是它应该做的:"年龄"one_answers"职业"的声明(但没有赋值(被挂起,所以控制台日志显示它们存在,值为"未定义"(而不是抛出ReferenceError
(,但name
很特别:你不是声明它的人,即使你的代码让它看起来像
真正发生的事情是,你写的代码是有范围的,所以当你说var name = "tom"
时,你实际上写的是currentscope.name = "tom"
。在任何类型的显式作用域(函数、模块等(中,这都将按照您预期的方式执行,但在浏览器中的全局作用域中(或者更准确地说,"在任何作用域为window
的执行上下文中"(,这意味着您的代码实际上以window.name = "tom"
的形式执行。
这就是问题所在:name
已经作为window
对象的全局属性存在
当然,这也适用于任何其他值,如果你在全局范围内var numbats = "cute";
,这与window.numbats = "cute";
相同,所以如果你不想遇到静默命名冲突:不要在全局范围中声明东西。在函数中测试这一点(其中var name
将覆盖全局name
(,或者您可以使用现代JS并使用let
而不是花括号块,但当然我们不再使用var
了。
有趣的鲜为人知的事实:将全局name
设置为"tom"
,然后在同一个选项卡中浏览一个小时,即使一个小时后,window.name
仍然是你的价值,除非其他人更改了它,这几乎从未发生过。这是一种有趣的方式,使多方面的跟踪成为可能。