[]
并且{}
在javascript中是真实的。
但我想将它们视为错误,并且我很想知道如何以尽可能少的字符来做到这一点:没有外部库或单独的函数,并且足够小以舒适地放在条件的括号之间。
换句话说:
检查未知变量(可以是任何类型)并在其中任何一个适用时返回的最简洁方法是什么
false
:a)它已经是假的;或 b) 它是{}
或[]
?
[]
并且{}
在javascript中是真实的。
但我想将它们视为错误,并且我很想知道如何以尽可能少的字符来做到这一点:没有外部库或单独的函数,并且足够小以舒适地放在条件的括号之间。
换句话说:
检查未知变量(可以是任何类型)并在其中任何一个适用时返回的最简洁方法是什么
false
:a)它已经是假的;或 b) 它是{}
或[]
?
数组最简洁的方式是!arr.length
. 当然,这假设您没有向数组中添加任何非索引属性(这是完全有效的做法)。正如Qantas 94 Heavy在评论中指出的那样,空数组可以将其length
设置为非零值,而不会获得任何实际条目。
对象更棘手。什么是“空”对象?一个根本没有属性?一个没有可枚举的属性?如果有的话,它的原型的属性呢?
如果没有可枚举的属性为你做这件事,在 ES5 中你可以使用!Object.keys(obj).length
. 如果你不能指望 ES5,你必须有一个循环:
var empty = true;
var key;
for (key in obj) {
// Add an `obj.hasOwnProperty(key)` check here if you want to filter out prototype properties
empty = false;
break;
}
...这显然是相当笨拙的。
你说过你不想要单独的函数,但当然这是最好的方法:
var isFalsey = (function() {
var toString = Object.prototype.toString;
function isFalsey(x) {
var key;
if (!x) {
return true;
}
if (typeof x === "object") {
if (toString.call(x) === "[object Array]") {
return !x.length; // Assumes no non-element properties in the array
}
for (key in x) {
// Add an `x.hasOwnProperty(key)` check here if you want to filter out prototype properties
return false;
}
return true;
}
return false;
}
return isFalsey;
})();
鉴于您有要检查的变量x
:
!(!x || x.length === 0 || JSON.stringify(x) === '{}')
在这里我们从后面开始,让我们检查是否x
为空:
!x
x.length === 0
{}
对象:JSON.stringify(x) === '{}'
小心JSON.stringify
方法。它适用于大多数现代浏览器,但如果您需要支持它们,则不适用于 IE6,7。你应该检查caniuse/JSON。
这些条件中的任何一个都为真将导致变量x
为空。
所以我们需要 or's ( ||
) 和 outer!
来反转结果以检查是否x
不为空。
编辑:
进行第三次检查的更简洁的方法是由于@David 备注(JSON.stringify
不适用于包含对象的方法,例如{a: function(){ console.log("test"); }}
):
(function (x){ for (key in x) { return 0; } return 1; })(x)
所以得到的表达式是:
!(!x || x.length === 0 || (function (x){ for (key in x) { return 0; } return 1; })(x))
编辑:
如果您只想支持现代浏览器,则不仅仅使用 ecmascript 5 功能:
// Given x is defined
!(!x || typeof x === 'object' && !Object.keys(x).length)
如果您知道该值是一个实例Array
或任何其他原语(而不是一般对象),那么您可以+
在对象前放一个符号并比较检查它是否是假的,如下所示:
> +[] == false
true
> +[1,2] == false
false
> +[] == false
true
> +true == false
false
> +'hello' == false
false
> +25 == false
false
> +false == false
true
如您所见,处理对象的一般实例更为复杂:
> +{} == false
false
> +{'a': 'b'} == false
false
或者如果你知道有问题的值绝对不是原始的,并且你使用的是 ES 5,那么你可以使用Object.keys
将对象的所有键作为数组获取,然后检查变成这样:
> +empty_obj == false || Object.keys(empty_obj) == false
true
> +obj == false || Object.keys(obj) == false
false
但是如果它是一个原始的,你就有麻烦了:
> +true == false || Object.keys(true) == false
TypeError: Object.keys called on non-object
at Function.keys (native)
at repl:1:27
at REPLServer.self.eval (repl.js:110:21)
at Interface.<anonymous> (repl.js:239:12)
at Interface.EventEmitter.emit (events.js:95:17)
at Interface._onLine (readline.js:202:10)
at Interface._line (readline.js:531:8)
at Interface._ttyWrite (readline.js:760:14)
at ReadStream.onkeypress (readline.js:99:10)
at ReadStream.EventEmitter.emit (events.js:98:17)
总而言之,您可以使用||
,&&
和==
运算符来尝试找到适用于所有情况的简短内容,但我不确定这是否可能。
因此,总而言之,我建议只使用@TJ Crowder 的答案中定义的函数。