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

2020/10/05 05:01 · javascript ·  · 0评论

声明变量之间有什么区别:

var a=0; //1

...这条路:

a=0; //2

...要么:

window.a=0; //3

在全球范围内?

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

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

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

这些陈述解释了

#1 var a = 0;

这将创建一个全局变量,该变量也是全局对象的属性,我们可以window在浏览器上(或通过this非严格代码通过全局范围访问)访问对象与其他某些属性不同,该属性无法通过删除delete

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

绑定(变量)是在第一行代码运行之前定义的(请参见var下面的“何时发生”)。

请注意,在IE8和更早版本上,on上创建的属性window不可枚举(不会显示在for..in语句中)。在IE9,Chrome,Firefox和Opera中,它是枚举的。


#1.1 let a = 0;

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

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

绑定是在其封闭块中的任何分步代码执行之前创建的(在这种情况下,在任何全局代码运行之前),但是在分步执行到达该语句之前,它无法以任何方式访问let一旦执行到达let语句,就可以访问该变量。(见“当letconst发生”的。)


#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"

现场示例:

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


letconst发生

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

因此,在运行时:

display(a);    // undefined
var a = 0;
display(a);    // 0

这将引发错误:

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

let与并const与问题区别var不大的其他两种方式是:

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

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

这是一个示例,该示例说明了这一点,letconst在该块中的任何代码运行之前立即在其块中生效,但要等到letorconst语句才能访问

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`
    }
})();

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

以这种方式使用的函数通常称为作用域函数在作用域函数定义的,因为他们是作用域函数可以访问的变量中定义的函数关闭了数据(见:瓶盖并不复杂在我贫血的小博客)。

保持简单:

a = 0

上面的代码提供了一个全局范围变量

var a = 0;

该代码将给出一个变量,该变量将在当前作用域及其下使用

window.a = 0;

这通常与全局变量相同。

<title>Index.html</title>
<script>
    var varDeclaration = true;
    noVarDeclaration = true;
    window.hungOnWindow = true;
    document.hungOnDocument = true;
</script>
<script src="external.js"></script>

/* external.js */

console.info(varDeclaration == true); // could be .log, alert etc
// returns false in IE8

console.info(noVarDeclaration == true); // could be .log, alert etc
// returns false in IE8

console.info(window.hungOnWindow == true); // could be .log, alert etc
// returns true in IE8

console.info(document.hungOnDocument == true); // could be .log, alert etc
// returns ??? in IE8 (untested!)  *I personally find this more clugy than hanging off window obj

是否有一个全局对象,默认情况下所有变量都挂起?例如:“ globals.noVar声明”

Bassed上的出色答卷TJ克罗德:(题外话:避免弄乱window

这是他的想法的一个例子:

HTML

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="init.js"></script>
    <script type="text/javascript">
      MYLIBRARY.init(["firstValue", 2, "thirdValue"]);
    </script>
    <script src="script.js"></script>
  </head>

  <body>
    <h1>Hello !</h1>
  </body>    
</html>

init.js(基于此答案

var MYLIBRARY = MYLIBRARY || (function(){
    var _args = {}; // private

    return {
        init : function(Args) {
            _args = Args;
            // some other initialising
        },
        helloWorld : function(i) {
            return _args[i];
        }
    };
}());

script.js

// Here you can use the values defined in the html as if it were a global variable
var a = "Hello World " + MYLIBRARY.helloWorld(2);

alert(a);

这是plnkr希望对您有所帮助!

在全局范围内,没有语义差异。

但是您确实应该避免,a=0因为您将值设置为未声明的变量。

还使用闭包来避免完全编辑全局范围

(function() {
   // do stuff locally

   // Hoist something to global scope
   window.someGlobal = someLocal
}());

在绝对必要时,请始终使用闭包,并始终将其提升到全局范围。无论如何,您应该对大多数通信使用异步事件处理。

正如@AvianMoncellor提到的那样,有一个IE错误,var a = foo仅声明文件范围的全局值。这是IE臭名昭著的解释器的问题。这个错误听起来确实很熟悉,所以可能是事实。

所以坚持 window.globalName = someLocalpointer

本文地址:http://javascript.askforanswer.com/javascriptzhongdebianliangshengmingyufabaokuoquanjubianliangzhijiandequbie.html
文章标签:
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!