空条件运算符

时间:2015-07-24 12:44:47

标签: javascript

C#6.0刚刚发布,并且有一个新的不错的小功能,我真的很想在JavaScript中使用它。他们被称为Null-conditional operators。它们使用?.?[]语法。

这些操作基本上允许您在尝试访问属性之前检查您获得的对象是否为null。如果对象为null,那么您将获得null作为您的财产访问权限的结果。

int? length = customers?.Length;

所以这里int可以为null,如果customers为null,则会取该值。更好的是你可以链接这些:

int? length = customers?.orders?.Length;

我不相信我们可以在JavaScript中做到这一点,但我想知道做类似事情的最好方法是什么。通常我发现链接if块难以阅读:

var length = null;
if(customers && customers.orders) {
    length = customers.orders.length;
}

4 个答案:

答案 0 :(得分:26)

被称为“可选链接”,它目前是Stage 1中的TC39提案。但是,Babel plugin已在v7中提供。

使用示例:

const obj = {
  foo: {
    bar: {
      baz: 42,
    },
  },
};

const baz = obj?.foo?.bar?.baz; // 42

const safe = obj?.qux?.baz; // undefined

答案 1 :(得分:14)

Js逻辑运算符不返回truefalse,但trulyfalsy值本身。例如,在表达式x && y中,如果x是假的,那么它将被返回,否则将返回y。所以运算符的真值表是正确的。

在您的情况下,您可以使用表达式customers && customers.orders && customers.orders.Length来获取length值或第一个falsy值。

你也可以像((customers || {}).orders || {}).length那样做一些魔术 (就个人而言,我不喜欢这种语法和可能的垃圾收集压力)

甚至使用maybe monad。

function Option(value) {
    this.value = value;
    this.hasValue = !!value;
}

Option.prototype.map = function(s) {
    return this.hasValue
        ? new Option(this.value[s])
        : this;
}

Option.prototype.valueOrNull = function() {
    return this.hasValue ? this.value : null;
}

var length = 
    new Option(customers)
        .map("orders")
        .map("length")
        .valueOrNull();

它比以前的所有方法都要长,但是在没有任何魔力的情况下清楚地表明了你的意图。

答案 2 :(得分:3)

有几种方法可以提高代码的可读性(取决于您的需求):

  1. 您已经使用(v7或更高版本),并且愿意使用"Optional Chaining" babel plugin(这仍然是第1阶段的建议):

    const length = customers?.orders?.Length;
    
    // With default value (otherwise it will be `undefined`):
    const length = customers?.orders?.Length || defaultLength;
    
    // File: .babelrc
    { "plugins": ["@babel/plugin-proposal-optional-chaining"] }
    
  2. 您已经使用(v3.7或更高版本):使用lodash.get方法:

    var length = _.get(customers, 'orders.length');
    
    // With default value (otherwise it will be `undefined`):
    var length = _.get(customers, 'orders.length', defaultLength);
    
  3. 普通的javascript:

    var length = customers && customers.orders && customers.orders.length;
    
    // With default value (otherwise it may be whatever falsy value "customers" or "customers.orders" might have):
    var length = (customers
        && customers.orders
        && customers.orders.length) || defaultLength;
    

答案 3 :(得分:0)

这是一个快速有效的版本。

String.prototype.nullSafe = function() {
    return eval('var x='+this.replace(/\?/g,';if(x)x=x')+';x');
};

用法示例:

var obj = { 
    Jim: 1,
    Bob: { "1": "B", "2": "o", "3": "b" },
    Joe: [ 1, 2, 3, { a: 20 } ]
};

 obj.Joe[3].a                  // 20    
"obj.Joe[3]?.a".nullSafe()    // 20

 obj.Joe[4].a                  // Error: Can't read 'a' from undefined
"obj.Joe[4].a".nullSafe()     // Error: Can't read 'a' from undefined
"obj.Joe[4]?.a".nullSafe()    // undefined

 obj.Jack[3].a.b              // Error: Can't read '3' from undefined
"obj.Jack[3].a.b".nullSafe()  // Error: Can't read '3' from undefined
"obj.Jack?[3].a.b".nullSafe() // undefined