3

假设我有一个 JavaScript 对象,例如:

var obj = {};
obj.computers = {};
obj.computers.favorite = "Commodore 64";
obj.computers.popular = "Apple";

现在,我可以轻松地检查 null,例如:

if(obj != 'undefined' && obj != null) {
    if(obj.computers != 'undefined' && obj.computers != null)) {
        .....

如您所见,如果我需要查看是否obj.computers.favorite已设置,我必须在其中真正嵌套一些条件逻辑。我们的一些对象有 3、4、5 层深。

这就是我希望能够做到的:

var fav = obj.computers.favorite || 'Unknown';

但我意识到我需要用某种方法来包装它。就像是:

var fav = getValueOrDefault(obj.computers.favorite, 'Unknown');

建议表示赞赏。

谢谢

编辑

我对“未定义”的检查实际上并不是我使用的。当我问这个问题时,它只是从我的脑海中浮现出来。哈哈

但我想知道,我可以只包装一个 try/catch 并在异常时抛出默认值吗?

function(obj, default) {
    try {
        if(obj != null) {
            return obj;
        } else {
            return default;
        }
    } catch(ex) {
        return default;
    }
}

另外,感谢 Shusi 指出多余的变量。

4

7 回答 7

6

你真的可以写:

(obj && obj.computers && obj.computers.favorite) || 'Unknown'
于 2012-10-01T20:25:05.117 回答
3

您可以使用辅助函数来完成。如果我正确理解您的问题,您的对象可能具有任意深度对象,并且您希望访问这些任意嵌套属性而不会弄乱您的代码。我构建了一个Nested函数,get()如果设置了任意属性,则可以使用该函数,如果未设置,则可以使用默认值。

var Nested = function() {};
// prop is a dot-separated path like "foo.bar.baz"
Nested.prototype.get = function(prop, _default) {
    var current = this;
    $.each(prop.split("."), function(i, e) {
        current = current[e] || undefined;
        if (current == undefined)
            return false;
    });
    return current || _default;
}

然后你可以写这样的代码

var fav = obj.get("computers.favourite", "Linux");
// this emulates
var fav = obj.computers.favourite || "Linux"; // throws error

正如你所看到的,打字并没有那么多。当然,它不像普通的 Javascript ......这是小提琴

于 2012-10-01T20:46:39.500 回答
3

我写这篇文章是为了帮助您处理您的一个问题:“我需要查看是否设置了 obj.computers.favorite ”。

Object.prototype.isset = function (/* string */ full_path)
{
    var props = full_path.split('.');
    var self = this; /* note that self is usually the window object */

    for (var ii = 0; ii < props.length; ++ii)
    {
        var prop = props[ii];
        var hasMoreComing = ii < props.length - 1 ? true : false;

        if (self[prop] !== null && typeof self[prop] === 'object' && hasMoreComing)
        {
            self = self[prop];
            continue;   // Move up one level.
        }
        else if (hasMoreComing)
            return false;    // ..because user queries a subproperty of a value type

        return self.hasOwnProperty(prop);
    }
};

测试代码:

var test = {};

test.kuk = {};
console.log( test.isset('kuk') );  // Prints true.

test.kuk.fitta = {};
console.log( test.isset('kuk.fitta') ); // Prints true.

test.kuk.fitta = null;
console.log( test.isset('kuk.fitta') ); // Prints true.

test.kuk.fitta = undefined;
console.log( test.isset('kuk.fitta') );  // Prints true

delete test.kuk.fitta;
console.log( test.isset('kuk.fitta') );  // Prints false

test.kuk.fitta = 123;
console.log( test.isset('kuk.fitta.doesnt.exist') );  // Prints false
于 2012-10-01T21:07:36.993 回答
1

以下函数将字符串作为参数,如果存在则返回对象

 function getValueOrDefault(str , obj, deflt){
    var a = str.split("."); o = obj;
    for(var i =0; i < a.length; i++){
         o = obj[a[i]];
         if(!o){
           return deflt;
         }
    }
      return o;
}

var obj = {};
obj.computers = {};
obj.computers.favorite = "Commodore 64";
obj.computers.popular = "Apple";
getValueOrDefault('computers.favorite', obj, 'Unknown');

注意:在将属性分配给对象时,不得使用 var,例如。var obj.computers.favorite 是语法错误。

于 2012-10-01T20:25:05.767 回答
1

不幸的是,没有一种超级简单的方法可以解决这个问题,但是您不需要同时检查 null 和 undefined。因为 null 和 undefined 都是假的,你可以这样做:

if (obj && obj.computers) {
  var fav = obj.computers.favorite || 'unknown';
}

它实际上并没有解决你的抱怨是什么,但它没有你想象的那么痛苦。

于 2012-10-01T20:25:42.257 回答
1

可选的链接运算符是处理此问题的更新方法:

let favorite = obj?.computers?.favorite;

将此与nullish coalescing operator结合使用,您可以精确地执行最初要求的操作:

let favorite = obj?.computers?.favorite ?? 'Unknown';

请注意,这些运算符都没有得到普遍支持。

于 2020-03-25T18:24:57.300 回答
0

您也可以使用JavaScript ES5 reduce函数执行此操作:

function get(root, member) {
    return member.split('.').reduce((acc, value) => {
        return (acc && typeof acc[value] !== 'undefined') ? acc[value] : undefined
    }, root);
}

它从成员字符串中创建一个数组,然后随着成员的减少,累加器逐渐在对象内遍历。

你可以像这样使用它,即使是数组:

let obj = {
    computers : {
        favorite : "Commodore 64",
        popular : "Apple",
        list: [
            {
                sn : "TDGE52343FD76",
                price: "9867.99",
                options: {
                    fanless: true
                }
            }
        ]
    }
}

get(obj, 'computers.popular');
// => "Apple"
get(obj, 'computers.list.0.sn');
// => "TDGE52343FD76"
get(obj, 'computers.list.0.options.fanless');
// => true
get(obj, 'computers.list.0.options.runsWithoutEletricity');
// => undefined
get(obj, 'computers.list.0.options.runsWithoutEletricity') || "too bad..." ;
// => "too bad..."

有一个codepen可以安全遍历js对象

于 2019-06-28T10:24:39.097 回答