use*_*934 102 javascript conditional-operator
例如,像这样:
var value = someArray.indexOf(3) !== -1 ? someArray.indexOf(3) : 0
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来写这个?同样,我不是在寻找上面确切问题的答案,只是一个例子,说明何时可能在三元运算符表达式中重复操作数...
sle*_*man 175
就个人而言,我发现最好的方法仍然是一个很好的if陈述:
var value = someArray.indexOf(3);
if (value === -1) {
value = 0;
}
Run Code Online (Sandbox Code Playgroud)
Dai*_*Dai 101
代码应该是可读的,所以简洁不应该意味着简洁无论成本 - 因为你应该重新发布到https://codegolf.stackexchange.com/ - 所以我建议使用第二个局部变量命名index以最大化阅读可理解性(运行成本最低,我注意到:):
var index = someArray.indexOf( 3 );
var value = index == -1 ? 0 : index;
Run Code Online (Sandbox Code Playgroud)
但是如果你真的想减少这种表达,因为你对你的同事或项目合作者来说是一个残酷的虐待狂,那么这里有4种方法你可以使用:
var声明中的临时变量当用逗号分隔时,您可以使用var语句的能力来定义(和分配)第二个临时变量index:
var index = someArray.indexOf(3), value = index !== -1 ? index: 0;
Run Code Online (Sandbox Code Playgroud)
另一种选择是自执行匿名函数:
// Traditional syntax:
var value = function( x ) { return x !== -1 ? x : 0 }( someArray.indexOf(3) );
// ES6 syntax:
var value = ( x => x !== -1 ? x : 0 )( someArray.indexOf(3) );
Run Code Online (Sandbox Code Playgroud)
JavaScript也支持臭名昭着的"逗号运算符",它也存在于C和C++中.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
如果要在需要单个表达式的位置包含多个表达式,可以使用逗号运算符.
您可以使用它来引入副作用,在这种情况下,通过重新分配到value:
var value = ( value = someArray.indexOf(3), value !== -1 ? value : 0 );
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为var value首先解释(因为它是一个语句),然后是最左边的,最里面的value赋值,然后是逗号运算符的右边,然后是三元运算符 - 所有合法的JavaScript.
评论员@IllusiveBrian指出,如果将赋值value用作带括号的子表达式,则不需要使用逗号运算符(在前面的示例中):
var value = ( ( value = someArray.indexOf(3) ) !== -1 ? value : 0 );
Run Code Online (Sandbox Code Playgroud)
请注意,在逻辑表达式中使用否定词可能更难以遵循 - 所以上述所有示例都可以通过更改idx !== -1 ? x : y为idx == -1 ? y : x:
var value = ( ( value = someArray.indexOf(3) ) == -1 ? 0 : value );
Run Code Online (Sandbox Code Playgroud)
Cri*_*par 53
对于数字
你可以使用这个Math.max()功能.
var value = Math.max( someArray.indexOf('y'), 0 );
Run Code Online (Sandbox Code Playgroud)
它将保持结果的边界,0直到第一个结果大于0情况.如果结果indexOf是-1,它将返回0大于-1.
对于布尔值和布尔值
对于JS,没有一般规则AFAIK特别是因为如何评估虚假值.
但是如果有什么东西可以帮助你,那么大部分时间都是或者运算符(||):
// Instead of
var variable = this_one === true ? this_one : or_this_one;
// you can use
var variable = this_one || or_this_one;
Run Code Online (Sandbox Code Playgroud)
你必须非常小心这一点,因为在你的第一个例子中,indexOf可以返回0,如果你评估0 || -1它会返回,-1因为它0是一个虚假值.
Tri*_*ych 26
不是,只是使用另一个变量.
你的例子概括为这样的东西.
var x = predicate(f()) ? f() : default;
Run Code Online (Sandbox Code Playgroud)
您正在测试计算值,然后在传递某个谓词时将该值分配给变量.避免重新计算计算值的方法很明显:使用变量来存储结果.
var computed = f();
var x = predicate(computed) ? computed : default;
Run Code Online (Sandbox Code Playgroud)
我理解你的意思 - 似乎应该有一些方法可以做到这一点,看起来更清洁.但我认为这是做到这一点的最好方式(惯用).如果由于某种原因你在代码中重复了这个模式,你可能会编写一个小帮助函数:
var setif = (value, predicate, default) => predicate(value) ? value : default;
var x = setif(someArray.indexOf(3), x => x !== -1, 0)
Run Code Online (Sandbox Code Playgroud)
Lyu*_*mir 17
使用 ||
const result = a ? a : 'fallback value';
相当于
const result = a || 'fallback value';
如果转换a为Boolean返回false,result则将被赋值'fallback value',否则为值a.
注意边缘情况下a === 0,其造型为false和result会(错误地)走'fallback value'.使用这样的技巧需要您自担风险.
PS.诸如Swift之类的语言具有nil-coalescing operator(??),它具有类似的用途.例如,在Swift中你会写result = a ?? "fallback value"一些非常接近JavaScript的东西const result = a || 'fallback value';
使用提取变量重构:
var index = someArray.indexOf(3);
var value = index !== -1 ? index : 0
Run Code Online (Sandbox Code Playgroud)
它const代替了更好var.你还可以做一个额外的提取:
const index = someArray.indexOf(3);
const condition = index !== -1;
const value = condition ? index : 0;
Run Code Online (Sandbox Code Playgroud)
在实践中,使用比更有意义的名称index,condition和value.
const threesIndex = someArray.indexOf(3);
const threeFound = threesIndex !== -1;
const threesIndexOrZero = threeFound ? threesIndex : 0;
Run Code Online (Sandbox Code Playgroud)
我个人更喜欢两种变体:
像@slebetman建议的那样纯粹
单独的函数,用默认值替换无效值,如下例所示:
function maskNegative(v, def) {
return v >= 0 ? v : def;
}
Array.prototype.indexOfOrDefault = function(v, def) {
return maskNegative(this.indexOf(v), def);
}
var someArray = [1, 2];
console.log(someArray.indexOfOrDefault(2, 0)); // index is 1
console.log(someArray.indexOfOrDefault(3, 0)); // default 0 returned
console.log(someArray.indexOfOrDefault(3, 123)); // default 123 returnedRun Code Online (Sandbox Code Playgroud)
您可能正在寻找一个合并运营商.幸运的是,我们可以利用Array原型创建一个:
Array.prototype.coalesce = function() {
for (var i = 0; i < this.length; i++) {
if (this[i] != false && this[i] != null) return this[i];
}
}
[null, false, 0, 5, 'test'].coalesce(); // returns 5
Run Code Online (Sandbox Code Playgroud)
通过向函数添加参数,可以进一步推广这种情况:
Array.prototype.coalesce = function(valid) {
if (typeof valid !== 'function') {
valid = function(a) {
return a != false && a != null;
}
}
for (var i = 0; i < this.length; i++) {
if (valid(this[i])) return this[i];
}
}
[null, false, 0, 5, 'test'].coalesce(); // still returns 5
[null, false, 0, 5, 'test'].coalesce(function(a){return a !== -1}); // returns null
[null, false, 0, 5, 'test'].coalesce(function(a){return a != null}); //returns false
Run Code Online (Sandbox Code Playgroud)
我喜欢@ slebetman的回答.其中的评论表达了对变量处于"中间状态"的担忧.如果这是你的一个大问题,那么我建议将其封装在一个函数中:
function get_value(arr) {
var value = arr.indexOf(3);
if (value === -1) {
value = 0;
}
return value;
}
Run Code Online (Sandbox Code Playgroud)
然后打电话
var value = get_value( someArray );
Run Code Online (Sandbox Code Playgroud)
如果你在其他地方使用它们,你可以做更多的通用功能,但如果它是一个非常具体的情况,不要过度工程.
但说实话,我会像@slebetman那样做,除非我需要从几个地方重新使用.