看起来:
if (typeof a == 'undefined') {
a = 0;
}
和
(typeof a != 'undefined') || (a = 0)
在JavaScript中具有相同的效果。
我很喜欢第二种方法,因为它是一行短小的代码,但这是否合法并且跨浏览器有效呢? 我的意思是,jslint说它有错误。我应该毫不担心地使用它吗?
看起来:
if (typeof a == 'undefined') {
a = 0;
}
和
(typeof a != 'undefined') || (a = 0)
在JavaScript中具有相同的效果。
我很喜欢第二种方法,因为它是一行短小的代码,但这是否合法并且跨浏览器有效呢? 我的意思是,jslint说它有错误。我应该毫不担心地使用它吗?
在我看来,|| (a = 0)
和 || (a == 0)
非常相似,因此容易让人混淆。有一天,过于热心的开发人员会仅仅"修复"它,改变你代码的意思。这样其他开发人员就需要花费一些时间来弄清楚这是否是你的意图还是一个简单的错误。
实际上,这正是JSLint试图传达的信息:
期望条件表达式,而看到的是一个赋值表达式。
我避免使用令人困惑的结构,因为它们会影响代码可读性。a = a || 0;
更易于识别,并且意义相似。
a = a || 0
不完全相同。对于false
和null
,你会得到0,这可能不是问答者想要的。 - Izkata为什么不使用更简单的方式,比如:
a = a || 0;
或者a = a ? a : 0;
在这两种情况下,你也可以清楚地看到在行的开头就将某些东西赋值给了 a
,而不需要阅读整个代码行,并弄清左侧或右侧是否发生了任何具有重大影响的函数调用... 或者弄清双方的功能,以决定可能存在多少潜在的程序范围变化。如果需要包含整个类型检查,它仍然不会非常庞大。a = (typeof a !== "undefined") ? a : 0; // [parentheses are there for clarity]
a = cond ? a : 0
是一个赋值语句,当然,a = a || 0
也是。你提到的额外赋值在哪里? - kojiroa
将被赋值为它本身,除非返回值为falsey,然后才会将其赋值为给定的默认值。同样,你的方法将鼓励开发人员修复OR语句(a === 0)
,或者重载它(a != 1) || (doStuff();doOtherStuff().id();a=16)
。就像那些已经使用三元运算符进行分支执行的人一样...这对于维护你的代码的人来说并不是一个好的结局。 - Norguard这是合法的,而且在所有EcmaScript引擎中都有效。然而,滥用短路求值作为if语句非常不常见。
我的意思是,jslint说它有错误。我能毫无顾虑地使用它吗?
不,JsLint是正确的。这种方法很不寻常和令人困惑,至少对其他开发者来说是这样。它看起来太像一个OR条件 - 然而它没有“主体”。如果你做赋值,变量应该在语句的开始,而不是在某个表达式内部。
我真的很喜欢第二个,因为它是简短的一行代码
那就使用它:
if (typeof a == 'undefined') a = 0;
您可以使用:
a = typeof(a) !== "undefined" ? a : 0;
(typeof a != 'undefined') || (a = 0)
是一个表达式。但其中一个子表达式
(a = 0)
这是一个任务。因此,本质上这是一个带有副作用的表达式。具有副作用的语句(特别是那些是表达式的语句)通常是你在入门编程课程中学习的首要事项之一,不要这样做。那么,仅仅因为它只需要一行代码,为什么要这样做呢?
我认为使用这样的结构很糟糕。虽然它可以工作,但代码不易读懂。如果你想要编写单行条件语句,可以开始使用CoffeeScript并编写:
a = 0 if (typeof a == 'undefined');
在您的情况下,当条件和赋值中只有一个变量时,请使用一行JavaScript三元运算符:
a = (typeof a == 'undefined') ? 0 : a;
请问您为什么偏爱一行代码呢?
作为人类,我更喜欢可读性强的代码。我的机器则更喜欢短小快速的代码(易于加载和执行)。
如今,像UglifyJS这样的代码压缩工具已经可以缩短代码,因此您可以同时拥有两者,而无需担心这个细节层面。我已将您的代码交给UglifyJS处理,以下是输出结果:
typeof a=="undefined"&&(a=0)
您可以在这里尝试一下:
【更新】考虑可读性,我的个人偏好是在有选择时使用 if,而在需要回退时使用 ||。你的具体示例似乎是一个回退(如果 a 不存在或未定义,则将值 0 分配给 a),因此我会使用 ||。正如我在评论中所说,在变量 a 尚未声明的情况下,(var a=0) 对我来说更有意义(我不知道您的上下文)。从风格上讲,像 a || a=default
这样设置默认值是进入函数时的常见习语,因为 JavaScript 不强制参数数量。
如果在其他情况下使用此结构,而你真正想要的是 if/else,则可读性将会受到影响。
性能以前在不同的风格之间有所差异,但在今天的快速测试中,if/else 和逻辑运算符的速度相同,但三元操作较慢。
a
赋值呢?这就是你提到的浪费。如果 a
是标量,那么你不会得到外部作用域的 a
的引用,而是标量值。如果 a
是对象,则要么你浪费时间赋值给 a
,因为你将通过返回值进行赋值(在 a
参数上浪费分配),要么你将对 a
进行对象构造,这不应该在那里完成,因为那是一个可维护性代码实例化的可怕位置。var b = doIt(a||obj);
就足够了。 - Norguardfunc(a,b,c)
,我可以只使用func()
来调用它。除非我在进入时设置默认参数值,否则一旦使用参数,我仍然必须检查未定义的值!在强类型语言中,您保证有值,并且引用可以保证传递了对象等。JavaScript没有保证这些事情。 - Phil Hfunction add(a, b) { return a + b; }
,那么 var c = add(a||a=0, b||b=0);
和 var c = add(a||0, b||0);
之间有什么区别。答案是对于 c
的目的来说,两者完全没有任何区别。 - Norguarda
或 b
,并且您打算在函数调用后继续使用它们...或者这是您的程序中唯一进行类型检查或验证的地方,那就是一个糟糕的地方来执行它。 - Norguardfunction add(a, b) { a || (a=0); b || (b=0); return a+b; }
。我同意,在进入函数时不希望初始化全局变量,但我并没有建议这样做。在 JavaScript 中,传递的是值,类似于 Java;按值传递值,按指针值传递对象。因此,函数可以测试其参数中是否有对象,如果没有,则构造一个默认对象。要求调用者执行此操作对调用者要求过高,并且暗示您永远不希望具有可选参数。 - Phil H(typeof a != 'undefined') || (a = 0)
由两个测试组成(即使我们不关心第二个测试)。
然而
if (typeof a == 'undefined') {
a = 0;
}
只包含一个测试
多年来,我一直讨厌“||代替IF”的写法。
现在我终于习惯了,并且喜欢上了这种写法。
我也喜欢用同样的方式使用“&&”。
如果你自己采用简洁的编码风格,阅读别人简洁的代码会更容易。
当然,我完全理解别人的想法。我也曾经历过这个阶段。
a = (typeof a !== 'undefined') ? a : 0
。该语句的意思是,如果变量a已经定义,则将其值赋给a,否则将a的值设置为0。 - Blender