设置 Javascript 对象属性的默认值

有没有一种方法可以设置 Javascript 对象的默认属性,以便:

let emptyObj = {};
// do some magic
emptyObj.nonExistingAttribute // => defaultValue
179370 次浏览

在 Javascript 中没有设置这一点的方法——返回不存在属性的 undefined是核心 Javascript 规范的一部分。见 对这个类似问题的讨论。正如我建议的那样,有一种方法(尽管我不是很推荐)可以定义一个全局 getProperty函数:

function getProperty(o, prop) {
if (o[prop] !== undefined) return o[prop];
else return "my default";
}


var o = {
foo: 1
};


getProperty(o, 'foo'); // 1
getProperty(o, 'bar'); // "my default"

But this would lead to a bunch of non-standard code that would be difficult for others to read, and it might have unintended consequences in areas where you'd expect or want an undefined value. Better to just check as you go:

var someVar = o.someVar || "my default";

我昨天看到一篇文章提到了一个 Object.__noSuchMethod__属性: JavascriptTips我还没有机会玩它,所以我不知道关于浏览器支持,但是也许你可以用它在某些方面?

这听起来像是典型的基于原型的对象:

// define a new type of object
var foo = function() {};


// define a default attribute and value that all objects of this type will have
foo.prototype.attribute1 = "defaultValue1";


// create a new object of my type
var emptyObj = new foo();
console.log(emptyObj.attribute1);       // outputs defaultValue1

或者你可以试试这个

dict = {
'somekey': 'somevalue'
};


val = dict['anotherkey'] || 'anotherval';

我的密码是:

function(s){
s = {
top: s.top || 100,    // default value or s.top
left: s.left || 300,  // default value or s.left
}
alert(s.top)
}

这对于 Object.create来说实际上是可能的。它不适用于“未定义”属性。但是对于那些已经被赋予了默认值的。

var defaults = {
a: 'test1',
b: 'test2'
};

然后,在创建属性对象时,使用 Object.create执行此操作

properties = Object.create(defaults);

Now you will have two object where the first object is empty, but the prototype points to the defaults object. To test:

console.log('Unchanged', properties);
properties.a = 'updated';
console.log('Updated', properties);
console.log('Defaults', Object.getPrototypeOf(properties));

我很惊讶还没有人提到三元运算符。

var emptyObj = {a:'123', b:'234', c:0};
var defaultValue = 'defaultValue';
var attr = 'someNonExistAttribute';
emptyObj.hasOwnProperty(attr) ? emptyObj[attr] : defaultValue;//=> 'defaultValue'




attr = 'c'; // => 'c'
emptyObj.hasOwnProperty(attr) ? emptyObj[attr] : defaultValue; // => 0

这样,即使‘ c’的值为0,它仍然会得到正确的值。

Since I asked the question several years ago things have progressed nicely.

代理是 ES6的一部分:

let handler = {
get: function(target, name) {
return target.hasOwnProperty(name) ? target[name] : 42;
}
};


let emptyObj = {};
let p = new Proxy(emptyObj, handler);


p.answerToTheUltimateQuestionOfLife; //=> 42

阅读更多 Mozilla 关于代理的文档

一种方法是使用默认对象并将其与目标对象合并。目标对象将重写默认对象中的值。

jQuery has the .extend() method that does this. jQuery is not needed however as there are vanilla JS implementations such as can be found here:

Http://gomakethings.com/vanilla-javascript-version-of-jquery-extend/

我认为最简单的方法是使用 Object.assign

如果你上这门课:

class MyHelper {
constructor(options) {
this.options = Object.assign({
name: "John",
surname: "Doe",
birthDate: "1980-08-08"
}, options);
}
}

你可以这样使用它:

let helper = new MyHelper({ name: "Mark" });
console.log(helper.options.surname); // this will output "Doe"

文件(含填料) : Https://developer.mozilla.org/it/docs/web/javascript/reference/global_objects/object/assign

使用 解体(ES6中新增)

这里有很棒的 Mozila 的文档,也有很棒的 博客文章,它比我能更好地解释语法。

回答你的问题

var emptyObj = {};
const { nonExistingAttribute = defaultValue } = emptyObj;
console.log(nonExistingAttribute); // defaultValue

继续前进

我可以 重命名这个变量吗? 当然!

const { nonExistingAttribute: coolerName = 15} = emptyObj;
console.log(coolerName); // 15

那么嵌套数据呢? 放马过来吧!

var nestedData = {
name: 'Awesome Programmer',
languages: [
{
name: 'javascript',
proficiency: 4,
}
],
country: 'Canada',
};


var {name: realName, languages: [{name: languageName}]} = nestedData ;


console.log(realName); // Awesome Programmer
console.log(languageName); // javascript
Object.withDefault = (defaultValue,o={}) => {
return new Proxy(o, {
get: (o, k) => (k in o) ? o[k] : defaultValue
});
}


o = Object.withDefault(42);
o.x  //=> 42


o.x = 10
o.x  //=> 10
o.xx //=> 42

Simplest of all Solutions:

dict = {'first': 1,
'second': 2,
'third': 3}

现在,

dict['last'] || 'Excluded'

将返回默认值‘ Exclused’。

我实现这一点的方法是使用 object.assign函数

const defaultProperties = { 'foo': 'bar', 'bar': 'foo' };
const overwriteProperties = { 'foo': 'foo' };
const newObj = Object.assign({}, defaultProperties, overwriteProperties);
console.log(defaultProperties);  // {"foo": "bar", "bar": "foo"}
console.log(overwriteProperties);  // { "foo": "foo" };
console.log(newObj);  // { "foo": "foo", "bar": "foo" }

我来这里寻找一个解决方案,因为头部符合我的问题描述,但它不是我所寻找的,但我得到了我的问题的解决方案(我想有一个属性的默认值,这将是动态的东西,如日期)。

let Blog = {
title  : String,
image  : String,
body   : String,
created: {type: Date, default: Date.now}
}

上面的代码是我最终决定的解决方案。

在我看来,这似乎是最简单易读的方法:

let options = {name:"James"}
const default_options = {name:"John", surname:"Doe"}


options = Object.assign({}, default_options, options)

Object.sign()引用

var obj = {
a: 2,
b: 4
};


console.log(obj);


--> {a: 2, b: 4}


function applyDefaults(obj) {
obj.a ||= 10;
obj.b ||= 10;
obj.c ||= 10;
}


// do some magic
applyDefaults(obj);


console.log(obj);


--> {a: 2, b: 4, c: 10}

这样做是因为

undefined || "1111111" --> "1111111"
"0000000" || "1111111" --> "0000000"

as null, undefined, NaN, 0, "" (Empty String), false itself, are all considered to be equivalent to false (假的). Anything else is true (真心话).

注意,不同浏览器和 nodejs 版本并不统一支持这一点(请自行确认)。

因此,两个麻烦的情况是空字符串 ""0(零)。如果重要的是不要覆盖它们,那么您可能需要将其重写为:

if (typeof obj.d == "undefined") obj.d = "default"

这也将在浏览器间得到更好的支持。

或者你可以这样写:

obj.d ??= "default"

这是仅适用于 nullundefined(无效)值的 无效作业,其中的空字符串是 没有的一部分。然而,这种跨浏览器的支持再次减弱。

另见 Mozilla 官方网站 为变量指定默认值

If you only have an object that is a 单层深度 (nested object properties will not merge as expected since it directly destructures from the first level), you can use the following destructuring syntax:

const options = {
somevar: 1234,
admin: true
};


const defaults = {
test: false,
admin: false,
};


var mergedOptions = {...defaults, ...options};

其中的产出将是:

console.log(options);
// { somevar: 1234, admin: true }


console.log(mergedOptions);
// { test: false, admin: true, somevar: 1234 }


或者甚至格式化为单个语句(尽管这有点不可读) :

const options = {...{
// Defaults
test: false,
admin: false,
}, ...{
// Overrides
somevar: 1234,
admin: true
}};

通过添加 逻辑零赋值运算符,您现在可以执行类似的操作

const obj = {}
obj.a ??= "default";

如果您有一个空列表作为默认值,并希望推送到它,那么您可以这样做

const obj = {}
(obj.a ??= []).push("some value")