Javascript相当于Python的dict.setdefault?

pto*_*ato 21 javascript dictionary

在Python中,对于字典d,

d.setdefault('key', value)
Run Code Online (Sandbox Code Playgroud)

d['key'] = value如果'key'不在d,否则离开它,因为它是.

有没有一种干净,惯用的方法在Javascript对象上执行此操作,还是需要if声明?

小智 26

现在你也可以这样做d.key ??= value

  • 惊人的!太感谢了。可能需要添加一个警告,只要“未定义”或“空”不允许条目合法存在(这种情况应该很少发生),这种情况就有效。而且,作为一个奖励,它是惰性的,因此表达式 `??= expr` 不会被不必要地评估。当我只需要访问单个代码块中的属性时,例如“(keyToList[key] ??= []).push”,我将使用它来替换 python 的“defaultdict”。 (5认同)
  • 作为参考,这称为“空合并赋值”。更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_assignment (3认同)

bob*_*ato 21

if (!('key' in d)) d.key = value;
Run Code Online (Sandbox Code Playgroud)

要么

'key' in d || (d.key = value);
Run Code Online (Sandbox Code Playgroud)

(最后一个使用条件表达式的短路行为.)


" d.key || (d.key = value)"在对方的回答是建议马车:如果一个元素存在,但计算结果为false(false,null,0,-0,"",undefined,NaN),它会被悄悄改写.

  • 虽然这可能是有意的,但它很可能不适用于所有上述情况.所以在这种情况下,请分别检查值:

    if (!('key' in d) || d.key === null) d.key = value;
    
    Run Code Online (Sandbox Code Playgroud)

  • 不仅仅是布尔人.`d.key`如果是以下任何一个则计算为false:`["",0,false,NaN,null,undefined]`,**或**如果实际上没有定义,那么测试可能会失败d用于存储字符串,数字,布尔值或对象.甚至可以拥有一个存在但仍保持值为"undefined"的属性(因为`d.key = undefined`与`delete d.key`不同). (2认同)

rob*_*les 9

它基本上就像使用if语句,但更短:

d.key || (d.key = value);
Run Code Online (Sandbox Code Playgroud)

要么

d.key = d.key || value;
Run Code Online (Sandbox Code Playgroud)

更新:正如@bobtato所指出的,如果属性已设置为值false,则会覆盖它,因此更好的方法是:

!d.key && d.key !== false && (d.key = value);
Run Code Online (Sandbox Code Playgroud)

或者,按照他的建议去做(只是缺少版本):

'key' in d || (d.key = value);

// including overwriting null values:

('key' in d && d.key !== null) || (d.key = value);
Run Code Online (Sandbox Code Playgroud)


Cra*_*aig 6

不建议这样做,增加内置类永远不是一个好主意.相反,最好创建自己的内置类实现,就像YUI库那样(YArray等).但是,我会反驳这一点,因为我经常发现像这样实现有用的捷径是编写干净的可维护代码的好处:

if (undefined === Object.prototype.setdefault) {
    Object.prototype.setdefault = function(key, def) {
        if (! this.hasOwnProperty(key)) {
            this[key] = def;
        }
        return this[key];
    };
}
Run Code Online (Sandbox Code Playgroud)

让我们看看它在行动......

var a = {};

a.setdefault('mylist', []).push(1);
a.setdefault('mylist', []).push(2);

console.log(a.mylist.toString());
    1,2
Run Code Online (Sandbox Code Playgroud)

正如已经指出的那样,使用它永远不是一个好主意,thing = thing || defaultThing因为它只测试非类型的等式true,或thing == true.与类型相等相反:thing === truething !== undefined.因此,setdefault以内联方式正确编码的唯一方法是在任何地方使用此代码段:

/* null == thing is equivalent to... */
if (undefined !== thing && null !== thing) {
    thing = defaultThing;
}
/* ...but it's not explicit and linters don't like it! */
Run Code Online (Sandbox Code Playgroud)

但正如我已经说过的,这只会给代码增加膨胀,并且容易出现"复制并粘贴"综合症所带来的错误.


DS.*_*DS. 5

没有内置的东西,但是这个功能可以做到:

function setDefault(obj, prop, deflt) {
  return obj.hasOwnProperty(prop) ? obj[prop] : (obj[prop] = deflt);
}
Run Code Online (Sandbox Code Playgroud)

如果obj只包含非伪造的值,obj[prop] || (obj[prop] = deflt)则是一个很好的简单替代方案(但deflt将覆盖任何伪造的值)。这具有额外的优点,即deflt仅在需要其值时才进行评估,因此可以将其作为昂贵的表达式使用。