为什么要显式将变量定义为未定义

Why explicitly define variable as undefined?

本文关键字:定义 未定义 变量 为什么      更新时间:2023-09-26

编辑:用他自己的话说:https://twitter.com/fogus/status/393058344413302784

我正在阅读Michael Fogus的"Functional JavaScript",并在第5章开头看到了这个列表:

function dispatch(/* funs */) {
    var funs = _.toArray(arguments);
    var size = funs.length;
    return function(target /*, args */) {
        var ret = undefined; // <----------------------------------- ??
        var args = _.rest(arguments);
        for (var funIndex = 0; funIndex < size; funIndex++) {
            var fun = funs[funIndex];
            ret = fun.apply(fun, construct(target, args));
            if (existy(ret)) return ret;
        }
        return ret;
     };
}

如果这不是一个错误,他为什么明确地将ret定义为undefined?这样做的一些更普遍的原因是什么?

提前谢谢。

人们这样做可能只是为了让读者更清楚地知道该值尚未定义,或者他明确希望该值undefined。 也就是说,他将值定义为 undefined .

但是没有语法上的理由这样做; 如果var foo;var foo = undefined;位于函数的开头,则它们会做同样的事情,并且在其他任何地方使用后者可能会破坏现有变量的值。

对你的问题的简短回答是让事情更明确。我不能保证作者为什么定义var ret = undefined;因为我不是作者。但是,我可以解释为什么在教东西时明确是一个好主意。尤其是当你教别人如何编码时。

我最喜欢的文章之一是Bret Victor关于可学习编程的著名博客文章(旁白:你必须阅读它 - 我坚持)。在这篇博文中,布雷特描述了人们如何比抽象概念更好地理解具体的例子。因此,通过明确,没有JavaScript经验的人更容易理解程序中发生的事情。

每个自称 JavaScript 程序员的人都必须知道,声明一个变量但不定义它会导致它被undefined(如果你考虑一下,这是很明显的)。因此,作者写var ret = undefined;或只是var ret;写没有任何区别。然而,前者更具体,更容易被新手理解。

然而,应该注意的是,undefined在 JavaScript 中不是一个保留字。因此,您可以创建一个名为undefined的变量,该变量很可能不是真正的undefined。在上述代码的上下文中,undefined实际上不能完全undefined。我们不确定,因为我们看不到dispatch的词汇环境。尽管如此,它很可能必须是undefined.

考虑到上述问题,将ret声明为var ret = void 0;会不那么模棱两可,也更明确。JavaScript 中的 void 运算符接受一个表达式并计算为 undefined 。因此,void expression总是计算为 undefined .然而,在给定的上下文中,简单地使用每个理智的JavaScript程序员都会做的var ret;会不那么混乱和模棱两可。

当然,这只是我为作者的决定辩护的解释。要获得更明确的答案,您需要询问作者本人。

在那种特定情况下,我看不出技术原因,这可能只是他的习惯或实践。当然,他可以这样声明ret

var ret;

在这种特定情况下,因为变量是局部的,就足够了。此外,它不会将变量的初始值用于任何内容(在循环中它只是分配它)。

但是,在更复杂的环境中,将变量显式设置为 undefined 可能是一种很好的做法。因为var没有声明块作用域变量,如果你有一个巨大的模块或主体函数——或者你在一个团队中工作,或者你在将不同的脚本发布到 Web 之前将它们组合在一起——那么你可能是重复使用同一个变量的名称两次,也许在两个不同的作用域中。在这种情况下,如果未显式设置该值,则将重用之前设置的值。为了明确这一点:

var ret = 10;
/* doing something with ret */
/* in the same scope, some lines above: */
if (someCondition) {
   var ret;
   console.log(ret); // 10, not `undefined`
}

发生这种情况是因为吊装:变量声明被移动到顶部,只剩下赋值。因为在if块中没有赋值,并且变量已经声明,所以那里的声明将被简单地删除。

请注意,相同的代码,开头没有var ret = 10会导致undefined:这就是为什么容易出错的原因。