栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Javascript中的变量声明语法(包括全局变量)之间的区别?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Javascript中的变量声明语法(包括全局变量)之间的区别?

是的,有一些差异,尽管实际上它们通常并不大。

还有第四种方法,从ES2015(ES6)开始,还有另外两种方法。我在最后添加了第四种方式,但是在#1之后插入了ES2015方式(您会看到原因),因此我们有:

var a = 0;     // 1let a = 0;     // 1.1 (new with ES2015)const a = 0;   // 1.2 (new with ES2015)a = 0;         // 2window.a = 0;  // 3this.a = 0;    // 4

这些陈述解释了

#1

var a = 0;

这将创建一个全局变量,该变量也是全局对象的属性,我们可以像

window
在浏览器上一样(或通过
this
非严格代码通过全局作用域访问)来访问它。与其他某些属性不同,该属性无法通过删除
delete

用规范的术语来说,它在全局环境的对象EnvironmentRecord_上创建一个标识符绑定。这使它成为全局对象的属性,因为全局对象是全局环境对象环境记录的标识符绑定所在的位置。这就是为什么该属性不可删除的原因:它不仅是一个简单的属性,还是一个标识符绑定。

绑定(变量)是在第一行代码运行之前定义的(请参见

var
下面的“何时发生”)。

请注意,在IE8和更早版本上,on上创建的属性

window
不可 枚举
(不会显示在
for..in
语句中)。在IE9,Chrome,Firefox和Opera中,它是枚举的。


#1.1

let a = 0;

这将创建一个 不是 全局对象属性的全局变量。从ES2015开始这是新事物。

用规范术语来说,它在声明性环境记录上为全局环境而不是对象环境记录创建一个标识符绑定。全球环境是具有开裂环境记录,一个对所有旧的东西就是那张在全局对象(独特的 对象
为所有新的东西,环境记录),另一个(

let
const
,和所创造的功能
class
)不继续使用全局对象。

绑定是在其封闭块中的任何分步代码执行之前创建的(在这种情况下,在任何全局代码运行之前),但是在分步执行到达该语句之前,它无法以任何方式
访问

let
。一旦执行到达
let
语句,就可以访问该变量。(见“当
let
const
发生”的。)


#1.2

const a = 0;

创建一个全局常量,它不是全局对象的属性。

const
完全一样,
let
除了必须提供一个初始化程序(
=value
一部分),并且一旦创建常量就无法更改其值。在幕后,这很像,
let
但是在标识符绑定上带有一个标志,表明其值无法更改。使用
const
可以为您做三件事:

  1. 如果您尝试分配给常量,则使其成为解析时错误。
  2. 记录其对于其他程序员的不变性。
  3. 让Javascript引擎在不会更改的基础上进行优化。

#2

a = 0;

这将在全局对象上 隐式 创建一个属性。由于它是普通属性,因此可以将其删除。我建议您
要这样做,以后再读您的代码的人可能会不清楚。如果使用ES5的严格模式,则执行此操作(将其分配给不存在的变量)是错误的。这是使用严格模式的几种原因之一。

有趣的是,再次在IE8和更早版本上,创建的属性不可 枚举 (不会显示在

for..in
语句中)。这很奇怪,特别是在下面的#3中。


#3

window.a = 0;

这将使用

window
引用全局对象的全局对象(在浏览器上;某些非浏览器环境具有等效的全局变量,例如
global
在NodeJS上)在全局对象上显式创建一个属性。由于它是普通属性,因此可以将其删除。

在IE8和更早版本以及我尝试过的所有其他浏览器上,此属性 都是 可枚举的。


#4

this.a = 0;

就像#3一样,除了我们通过引用全局对象

this
而不是引用global
window
。但是,这在严格模式下将不起作用,因为在严格模式下,全局代码
this
没有对全局对象的引用(而是具有值
undefined
)。


删除属性

“删除”或“删除”是什么意思

a
?正是这样:通过
delete
关键字完全删除属性:

window.a = 0;display("'a' in window? " + ('a' in window)); // displays "true"delete window.a;display("'a' in window? " + ('a' in window)); // displays "false"

delete
完全从对象中删除属性。你不能做到这一点与特性加入到
window
通过间接
var
时,
delete
要么悄悄地忽略或抛出一个异常(取决于Javascript实现,以及是否你在严格模式)。

警告
:IE8再次出现(可能是更早的版本,而IE9-IE11处于损坏的“兼容性”模式):

window
即使您允许,它也不允许您删除对象的属性。更糟糕的是,尝试时会引发异常(在IE8和其他浏览器中尝试此实验)。因此,从
window
对象中删除时,您必须具有防御性:

try {    delete window.prop;}catch (e) {    window.prop = undefined;}

这会尝试删除该属性,如果引发异常,它将做第二件事,并将属性设置为

undefined


适用于该

window
对象,并且仅(据我所知)适用于IE8和更早的版本(或处于“兼容”模式的IE9-IE11)。其他浏览器可以删除
window
属性,但要遵守上述规则。


何时
var
发生

通过该

var
语句定义的变量是在运行上下文中的任何逐步代码运行之前创建的,因此该属性早于该
var
语句存在。

这可能会造成混淆,所以让我们看一下:

display("foo in window? " + ('foo' in window)); // displays "true"display("window.foo = " + window.foo);          // displays "undefined"display("bar in window? " + ('bar' in window)); // displays "false"display("window.bar = " + window.bar);          // displays "undefined"var foo = "f";bar = "b";display("foo in window? " + ('foo' in window)); // displays "true"display("window.foo = " + window.foo);          // displays "f"display("bar in window? " + ('bar' in window)); // displays "true"display("window.bar = " + window.bar);          // displays "b"

现场示例:

display("foo in window? " + ('foo' in window)); // displays "true"display("window.foo = " + window.foo);          // displays "undefined"display("bar in window? " + ('bar' in window)); // displays "false"display("window.bar = " + window.bar);          // displays "undefined"var foo = "f";bar = "b";display("foo in window? " + ('foo' in window)); // displays "true"display("window.foo = " + window.foo);          // displays "f"display("bar in window? " + ('bar' in window)); // displays "true"display("window.bar = " + window.bar);          // displays "b"function display(msg) {  var p = document.createElement('p');  p.innerHTML = msg;  document.body.appendChild(p);}

如您所见,符号

foo
在第一行之前定义,但符号未定义
bar
。该
var foo ="f";
语句所在的地方实际上有两件事:定义符号,它发生在代码的第一行运行之前;并对该符号进行赋值,该操作会在分步流程中的直线处发生。这被称为“
var
提升”,因为
varfoo
零件已移动(“提升”)到示波器的顶部,但
foo = "f"
零件仍保留在其原始位置。


let
const
发生

let
并且在几个方面
const
有所不同
var
。与该问题相关的方式是,尽管它们定义的绑定是在任何分步代码运行之前创建的,但是直到到达or
语句之后,才能访问该绑定。
let``const

因此,在运行时:

display(a);    // undefinedvar a = 0;display(a);    // 0

这将引发错误:

display(a);    // ReferenceError: a is not definedlet a = 0;display(a);

let
const
区别的其他两种方式与
var
问题并不真正相关,分别是:

  1. var
    始终适用于整个执行上下文(整个全局代码,或者贯穿在它出现的功能函数代码),但
    let
    const
    仅在适用 在那里出现。也就是说,
    var
    具有功能(或全球)的范围,但
    let
    const
    有块范围。

  2. var a
    在相同的上下文中重复是没有害处的,但是如果您有
    let a
    (或
    const a
    ),则具有另一个
    let a
    或a
    const a
    或a
    var a
    是语法错误。

这是一个示例,该示例演示了该操作

let
const
在该块中的任何代码运行之前立即在其块中生效,但是直到
let
or
const
语句才能访问:

var a = 0;console.log(a);if (true){  console.log(a); // ReferenceError: a is not defined  let a = 1;  console.log(a);}

请注意,第二个

console.log
失败,而不是
a
从块外部访问。


离题:避免使全局对象混乱(
window

window
对象的属性变得非常混乱。只要有可能,强烈建议不要增加混乱。而是将符号包装在一个小包装中,并将最多一个符号导出到
window
对象。(我经常不将任何符号导出到该
window
对象。)您可以使用函数包含所有代码以包含符号,并且如果您愿意,该函数可以是匿名的:

(function() {    var a = 0; // `a` is NOT a property of `window` now    function foo() {        alert(a);   // alerts "0", because `foo` can access `a`    }})();

在该示例中,我们定义一个函数并立即执行它(

()
最后是)。

以这种方式使用的函数通常称为作用域函数。在作用域函数定义的,因为他们是作用域函数可以访问的变量中定义的函数关闭了数据



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/456666.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号