Javascript 为什么显式地将变量定义为未定义?

Javascript 为什么显式地将变量定义为未定义?,javascript,functional-programming,Javascript,Functional Programming,编辑:用他自己的话来说: 我正在阅读Michael Fogus的“Functional JavaScript”,并在第5章开头看到了以下列表: function dispatch(/* funs */) { var funs = _.toArray(arguments); var size = funs.length; return function(target /*, args */) { var ret = undefined; // <--

编辑:用他自己的话来说:

我正在阅读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;
     };
}
函数分派(/*funs*/){
var funs=uu.toArray(参数);
变量大小=函数长度;
返回函数(target/*,args*/){

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


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

在这种情况下,我看不出技术原因,这可能只是一种习惯或实践当然,他可以声明如下:
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
,将导致
未定义的
:这就是为什么可能容易出错的原因。

你的问题的简短答案是让事情更加明确。我无法证明作者为什么定义
var ret=undefined;
,因为我不是au然而,我可以解释为什么当你在教一些东西的时候,明确表达是个好主意。尤其是当你在教别人如何编码的时候

我最喜欢的一篇文章是布雷特·维克托(Bret Victor)在上发表的著名博文(旁白:你必须读——我坚持)。在这篇博文中,Bret描述了人们如何更好地理解具体的例子而不是抽象的概念。因此,通过明确,一个没有JavaScript经验的人更容易理解程序中发生的事情

每个自称为JavaScript程序员的人都必须知道,声明一个变量而不定义它会导致它
未定义
(仔细想想,这是很明显的)因此,无论作者是编写
var-ret=undefined;
还是简单地编写
var-ret;
,都没有任何区别。但是前者更具体,更容易被新手理解

但是需要注意的是,
undefined
在JavaScript中不是一个保留字。因此,您可以创建一个名为
undefined
的变量,该变量很可能不是真正的
undefined
。在上面的代码上下文中,
undefined
实际上不可能是
undefined
的。我们不知道它是什么当然可以,因为我们看不到
dispatch
的词法环境。不过,它很可能是
未定义的

考虑到上述问题,将
ret
声明为
var-ret=void 0;
将不那么模棱两可,更为明确。JavaScript中的
void
操作符接受一个表达式并计算为
undefined
。因此
void expression
总是计算为
undefined
。但是在给定的条件下简单地使用
var-ret;
(每一个理智的JavaScript程序员都会这么做)会减少混乱和歧义


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

要设置默认值吗?我会选择
var-ret
var-ret=null
,但每个人都有自己的选择。一个非常疯狂的猜测是,他喜欢一种所有变量都声明并初始化的编码方式在定义它们的作用域开始时就被定义了。AFAIK没有理由做var ret=undefined。相反,在旧版本的ES中,如果undefined被重新定义为其他内容,这将使代码易受攻击。@Tibos这正是我在回答中解释的:=)这是有意义的;我的同事说:“这是一个选择,告诉读者undefined是一个合法的返回值,而不是意外的赋值失败。"@ggUndefined嘿,
undefined
可能实际上不是
undefined
。作者可能是一个虐待狂,错误地声明
var-ret=undefined;
其中
undefined
可能是父作用域中声明的某个默认值。你永远不知道。请阅读我的答案以了解更多详细信息:替换
var-ret的问题
var ret=undefined;
但是,如果外部代码没有与
ret
一起完成,那就太糟糕了——您刚刚覆盖了它的值。这就是为什么有些人建议在函数开始时声明所有变量的原因。(我认为这有点过于僵化,但至少需要了解JS中的变量范围)。这就是为什么我们有<代码>让,现在,一个常见的场景可以是一个<代码> i <代码>,用于循环和其他东西,或者一些通用的名称,如<代码>和> />代码。在大多数情况下,我讨论了(例如组合不同的文件)。,通常是黄色的