Javascript equivalent of Python's dict.setdefault?

Javascript equivalent of Python's dict.setdefault?

本文关键字:dict setdefault equivalent of Python Javascript      更新时间:2023-09-26

在Python中,对于字典d

d.setdefault('key', value)
如果'key'不在d中,

设置d['key'] = value,否则保持不变。

在Javascript对象上是否有一种干净、习惯的方法来做到这一点,或者它是否需要if语句?

if (!('key' in d)) d.key = value;

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

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


在另一个答案中建议的" d.key || (d.key = value) "是错误的:如果一个元素存在但求值为false (false, null, 0, -0, "", undefined, NaN),它将被静默覆盖。

  • 虽然这可能是有意的,但它很可能不是为上述所有的情况而设计的。因此,在这种情况下,分别检查值:

    if (!('key' in d) || d.key === null) d.key = value;
    

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

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

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

d.key = d.key || value;

更新:正如@bobtato所指出的,如果属性已经设置为false的值,它将覆盖它,所以一个更好的方法是:

!d.key && d.key !== false && (d.key = value);

或者,按照他的建议去做(只是简写版):

'key' in d || (d.key = value);
// including overwriting null values:
('key' in d && d.key !== null) || (d.key = value);

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

function setDefault(obj, prop, deflt) {
  return obj.hasOwnProperty(prop) ? obj[prop] : (obj[prop] = deflt);
}

如果obj只包含非假值,obj[prop] || (obj[prop] = deflt)是一个很好的简单替代(但deflt将覆盖任何假值)。这还有一个额外的好处,即deflt只在需要它的值时才会被计算,所以它是一个昂贵的表达式也是可以的。

不建议,也绝不是增加内置类的好主意。相反,最好创建自己的内置类实现,就像YUI库所做的那样(YArray等)。然而,我要反驳这一点,因为我经常发现实现像这样有用的快捷方式对于编写干净的可维护代码是有好处的:

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

让我们看看它的实际效果…

var a = {};
a.setdefault('mylist', []).push(1);
a.setdefault('mylist', []).push(2);
console.log(a.mylist.toString());
    1,2

正如已经指出的,使用thing = thing || defaultThing从来都不是一个好主意,因为它只测试truething == 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! */

但是,正如我已经说过的,这只会增加您的代码的膨胀,并且容易从"复制-粘贴"综合症中获得错误。

a={}
key='3'
value = 2
a[key] = a[key] == undefined ? value : a[key]
## a = {'3': 2 }

Typescript版本的@DS。的回答是:

export function setDefault<K extends string | number | symbol, T>(
  obj: Record<K, T>,
  prop: K,
  deflt: T,
) {
  // eslint-disable-next-line
  return obj.hasOwnProperty(prop) ? obj[prop] : (obj[prop] = deflt);
}

// eslint-disable-next-line行旨在忽略以下eslint错误:

  9:3   error  Return statement should not contain assignment                             no-return-assign
  9:14  error  Do not access Object.prototype method 'hasOwnProperty' from target object  no-prototype-builtins
  9:50  error  Assignment to property of function parameter 'obj'                         no-param-reassign

如果有人知道如何改进解决方案,使这些错误被修复而不是被忽略,请告诉我。
老实说,如果不分配obj参数,我不知道如何实现这一点。