1

[]并且{}在javascript中是真实的。

但我想将它们视为错误,并且我很想知道如何以尽可能少的字符来做到这一点:没有外部库或单独的函数,并且足够小以舒适地放在条件的括号之间。

换句话说:

检查未知变量(可以是任何类型)并在其中任何一个适用时返回的最简洁方法是什么falsea)它已经是假的;或 b) 它是{}[]

4

3 回答 3

4

数组最简洁的方式是!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;
})();

测试示例来源

于 2013-10-20T10:23:38.773 回答
3

鉴于您有要检查的变量x

!(!x || x.length === 0 || JSON.stringify(x) === '{}')

在这里我们从后面开始,让我们检查是否x为空:

  1. 它可能已经是虚假的:!x
  2. 它是 Array 并且它的长度为零:x.length === 0
  3. 它正是{}对象: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)
于 2013-10-20T10:38:01.357 回答
0

如果您知道该值是一个实例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 的答案中定义的函数。

于 2013-10-20T11:42:54.567 回答