Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript全局范围分配_Javascript_Global Variables - Fatal编程技术网

Javascript全局范围分配

Javascript全局范围分配,javascript,global-variables,Javascript,Global Variables,我理解全局范围和javascript变量的问题以及它们的一般不受欢迎性;你到处都能找到它们。以下内容(在浏览器中)是等效的: var foo = 3; // foo === 3, window.foo === 3 bazz = 10; // bazz === 10, window.bazz === 10 在全局范围中使用var关键字声明变量与在代码中任何地方不使用var声明变量相同:您的变量被分配给根(窗口)对象 我经常看到的一种技术(例如,设置google analytics)是: 。。。我

我理解全局范围和javascript变量的问题以及它们的一般不受欢迎性;你到处都能找到它们。以下内容(在浏览器中)是等效的:

var foo = 3; // foo === 3, window.foo === 3
bazz = 10; // bazz === 10, window.bazz === 10
在全局范围中使用var关键字声明变量与在代码中任何地方不使用var声明变量相同:您的变量被分配给根(窗口)对象

我经常看到的一种技术(例如,设置google analytics)是:

。。。我遵循的推理是,如果_gaq已被声明,则使用它,如果不使用它,则将其创建为数组。它允许粗心的编码不会覆盖已分配给全局变量_gaq的任何值

我不明白的是为什么会出现错误:

_gaq = _gaq || [];

它们看起来和我一样:_gaq应该取_gaq的值,或者初始化为数组。但是它抛出了一个引用错误-我的问题是:它们为什么不同?

如果
=
右侧的
\u gaq
之前没有用
var
声明,它将抛出一个引用错误。您试图引用一个不存在的变量。“魔法”只适用于分配给不存在的变量


这就像说
x=y+1
;问题不在于不存在的
x
,而在于不存在的
y

您永远无法读取未声明的变量,这就是您在最后一种情况下尝试使用表达式
|gaq|124;[]

在这种情况下

 _gaq = _gaq || [];
\u qaq
之前未声明,当计算右侧(
\u gaq | |【】
)时,它抛出错误

以下是本案例中发生的情况的逐步说明:

赋值运算符在规范的第1部分中描述:

production
AssignmentExpression:LeftHandSideExpression=AssignmentExpression
的计算如下:

一,。让
lref
作为计算
LeftHandSideExpression
的结果
2.让
rref
作为计算
AssignmentExpression
的结果

lefthandideexpression
\u gaq
赋值表达式是
\u gqa |【】

因此首先计算
\u qaq
,这会导致一个,因为变量
\u gaq
没有声明。此评估不会引发错误

_gaq = _gaq || [];
然后计算
\u gqa | |[]
。这是一个
LogicalORExpression
,在中描述为
LogicalORExpression | | logicaladexpression
。在这种情况下,
LogicalORExpression
左侧为
\u gaq
,而
logicaladexpression
右侧为
[]

表达式的计算如下所示:

一,。让
lref
作为计算
LogicalORExpression
的结果
2.让
lval
be
GetValue(lref)

我们已经知道,
lref
将是一个无法解决的引用,因为没有声明
\u gaq
。因此,让我们看看
GetValue
正在做什么(在中定义,
V
是传递给
GetValue
的值):

一,。如果
Type(V)
不是
Reference
,则返回
V

2.让
base
成为调用
GetBase(V)
的结果
3.如果
isUnsolvableReference(V)
,则抛出
ReferenceError
异常。

正如您所看到的,在这个过程的第三步中抛出了一个
ReferenceError
错误,然后通过计算赋值的右侧来执行,这就是抛出错误的地方

那么,为什么
var _gaq=_gaq | |[]不会发生这种情况呢

这一行:

var _gaq = _gaq || [];
实际上是

var _gaq;
_gaq = _gaq || [];
因为一种叫做。这意味着当计算
\u gaq
时,它将不会导致不可解析的引用,而是导致值
未定义的引用

(如果变量
\u gaq
已经声明(并且可能有一个值),那么
var\u gaq
将不会有任何效果。)


如果要从函数内部全局创建
\u gaq
,请参考
窗口

window._gaq = window._gaq || [];

这将引发错误,因为在当前执行上下文的上下文链中找不到该变量。访问无法解析的变量将导致错误

_gaq = _gaq || [];
另一方面,这将试图解决gac试图将其作为窗口对象的成员查找的问题,而窗口对象是全局上下文“持有者”对象。这种情况的不同之处在于它不会抛出错误,但是
窗口将返回undefined,因为在窗口对象中找不到该属性

_gaq = window._gaq || [];

因此,由于全局上下文对象是窗口(当谈到浏览器时),如果定义了_gaq,这两条语句将具有相同的效果。当未定义_gaq时,会注意到差异,使用窗口对象访问它可以具有不出错的优势。

这里有一个基本概念,在实践中通常很棘手。变量定义在函数作用域的顶部,而赋值仍然发生在定义变量的位置

_gaq = _gaq || [];
使用这个
var\u gaq=\u gaq
变量实际上是在执行赋值的实际代码行之前定义的。这意味着当赋值发生时,变量已经在窗口范围内。如果在_gaq前面没有var,则不会发生提升,因此,当分配运行导致参考错误时,还不存在_gaq

如果您想看到这一点,您可以通过以下方式检查_gaq变量何时添加到窗口对象:

function printIsPropOnWindow(propToCheck)
{
    for (prop in window)
    {
        if (prop == propToCheck)
        {
            console.warn('YES, prop ' + prop + ' was on the window object');
            return;
        }
    }
    console.warn('NO, prop ' + propToCheck + ' was NOT on the window object');
}


try {
    var _gaq = function() {
        printIsPropOnWindow("_gaq");
        return a;
    }();
} catch (ex) {
    printIsPropOnWindow("_gaq");
}
_gaq = "1";
printIsPropOnWindow("_gaq");
如果您按原样尝试一次,并且在使用var之前尝试一次_gaqre