javascript 如果未定义,则自动创建对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17643965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Automatically create object if undefined
提问by Marcel Gwerder
Is there an easy way to automatically add properties to objects if they don't allready exist?
如果对象不存在,是否有一种简单的方法可以自动向对象添加属性?
Consider the following example:
考虑以下示例:
var test = {}
test.hello.world = "Hello doesn't exist!"
This doesn't work because hello
isn't defined.
这不起作用,因为hello
没有定义。
The reason why I'm asking this is because I have some existing objects for which I don't know if they allready have hello
or not. I actually have a lot of these objects in different parts of my code.
It is very annoying to always check if hello
exists and if it doesn't create a new object like:
我问这个的原因是因为我有一些现有的对象,我不知道它们是否已经有了hello
。我的代码的不同部分实际上有很多这些对象。总是检查是否hello
存在以及是否不创建新对象是非常烦人的,例如:
var test = {}
if(test.hello === undefined) test.hello = {}
test.hello.world = "Hello World!"
Is there a way to automatically create an object like hello
in this example?
有没有办法像hello
这个例子一样自动创建一个对象?
I mean something like that in php:
我的意思是在 php 中是这样的:
$test = array();
$test['hello']['world'] = "Hello world";
var_dump($test);
Output:
输出:
array(1) {
["hello"]=>
array(1) {
["world"]=>
string(11) "Hello world"
}
}
Ok it's an array but in js arrays it is the same problem as with objects.
好的,它是一个数组,但在 js 数组中,它与对象存在相同的问题。
回答by xbonez
var test = {};
test.hello = test.hello || {};
test.hello.world = "Hello world!";
If test.hello
is undefined, it gets set to an empty object.
如果test.hello
未定义,则将其设置为空对象。
If test.hello
was previously defined, it stays unchanged.
如果test.hello
之前已定义,则保持不变。
var test = {
hello : {
foobar : "Hello foobar"
}
};
test.hello = test.hello || {};
test.hello.world = "Hello World";
console.log(test.hello.foobar); // this is still defined;
console.log(test.hello.world); // as is this.
回答by columbus
New object
新对象
myObj = {};
recursive function
递归函数
function addProps(obj, arr, val) {
if (typeof arr == 'string')
arr = arr.split(".");
obj[arr[0]] = obj[arr[0]] || {};
var tmpObj = obj[arr[0]];
if (arr.length > 1) {
arr.shift();
addProps(tmpObj, arr, val);
}
else
obj[arr[0]] = val;
return obj;
}
Call it with a dot notated string
用点符号字符串调用它
addProps(myObj, 'sub1.sub2.propA', 1);
or with an array
或使用数组
addProps(myObj, ['sub1', 'sub2', 'propA'], 1);
and your object will look like this
你的对象看起来像这样
myObj = {
"sub1": {
"sub2": {
"propA": 1
}
}
};
It works with non-empty objects too!
它也适用于非空对象!
回答by Blender
You won't be able to do this without some sort of function, as JavaScript doesn't have a generic getter/setter method for objects (Python, for example, has __getattr__
). Here's one way to do it:
如果没有某种函数,您将无法做到这一点,因为 JavaScript 没有用于对象的通用 getter/setter 方法(例如,Python 有__getattr__
)。这是一种方法:
function add_property(object, key, value) {
var keys = key.split('.');
while (keys.length > 1) {
var k = keys.shift();
if (!object.hasOwnProperty(k)) {
object[k] = {};
}
object = object[k];
}
object[keys[0]] = value;
}
If you really want to, you could add it to the prototype of Object
. You can call it like so:
如果你真的想要,你可以将它添加到Object
. 你可以这样称呼它:
> var o = {}
> add_property(o, 'foo.bar.baz', 12)
> o.foo.bar.baz
12
回答by basilikum
Well you could extend the prototype of Object
with a function that return a property, but adds it first, if it doesn't exist:
好吧,您可以Object
使用返回属性的函数扩展 的原型,但如果它不存在,则首先添加它:
Object.prototype.getOrCreate = function (prop) {
if (this[prop] === undefined) {
this[prop] = {};
}
return this[prop];
};
var obj = {};
obj.getOrCreate("foo").getOrCreate("bar").val = 1;
回答by John Neuhaus
Here's a cool version with proxies:
这是一个带有代理的很酷的版本:
const myUpsert = (input) => {
const handler = {
get: (obj, prop) => {
obj[prop] = obj[prop] || {};
return myUpsert(obj[prop]);
}
};
return new Proxy(input, handler);
};
And you use it like this:
你像这样使用它:
myUpsert(test).hello.world = '42';
This will add all the missing properties as empty objects, and leave the existing ones untouched. It's really just a proxied version of the classic test.hello = test.hello || {}
, albeit much slower (See benchmark here.) But it's also much nicer to look at, especially if you'll be doing it more than one level deep. I wouldn't pick it for performance-heavy data crunching, but it's probably fast enough for a front-end state update (as in Redux).
这会将所有缺失的属性添加为空对象,并保持现有属性不变。它实际上只是经典的代理版本test.hello = test.hello || {}
,虽然速度要慢得多(请参阅此处的基准测试。)但它看起来也更好看,尤其是如果您要进行不止一个级别的深度处理。我不会选择它来处理性能繁重的数据处理,但它可能足够快以用于前端状态更新(如在 Redux 中)。
Note that there's some implicit assumptions here:
请注意,这里有一些隐含的假设:
- The intervening properties are either objects or non-existent. This will choke if
test.hello
is a string, for example. - That you always want to be doing this for as long as you're using the Proxy instead of the original object.
- 中间属性要么是对象,要么不存在。
test.hello
例如,如果是字符串,这将阻塞。 - 只要您使用代理而不是原始对象,您就一直希望这样做。
These are pretty easily mitigated if you only use it in well-bounded contexts (like a reducer body) where there's little chance of accidentally returning the Proxy, and not much else you would want to do with the object.
如果您只在有界上下文(如减速器主体)中使用它,那么这些很容易缓解,在这种情况下,意外返回代理的可能性很小,并且您不想对对象做太多其他事情。
回答by Shawn31313
var test = {}
if(!test.hasOwnProperty('hello')) {
test.hello = {};
}
test.hello.world = "Hello World!"
回答by holographic-principle
This will add a property hello
whose value is {world: 'Hello world!'}
to the test object, if it doesn't exist. If you have a lot of these objects, you can just iterate over them and apply this function. Note: uses lodash.js
这将添加一个属性,hello
其值是{world: 'Hello world!'}
测试对象,如果它不存在。如果你有很多这样的对象,你可以迭代它们并应用这个函数。注意:使用lodash.js
var test = {};
_.defaults(test, { hello: {world: 'Hello world!'} });
Which is actually a convenience method for saying:
这实际上是一种方便的说法:
var defaults = _.partialRight(_.assign, function(a, b) {
return typeof a == 'undefined' ? b : a;
});
defaults(test, { hello: {world: 'Hello world!'} });
Note: _.defaults
uses loops to achieve the same thing as the second block.
注意:_.defaults
使用循环来实现与第二个块相同的事情。
P.S. Checkout https://stackoverflow.com/a/17197858/1218080
回答by Michal Politzer
I use this:
我用这个:
Object.prototype.initProperty = function(name, defaultValue) {
if (!(name in this)) this[name] = defaultValue;
};
You can later do f.e.:
你以后可以做fe:
var x = {a: 1};
x.initProperty("a", 2); // will not change property a
x.initProperty("b", 3); // will define property b
console.log(x); // => {a: 1, b: 3}
回答by VIKAS KOHLI
var test = {}
test.hello.world = "Hello doesn't exist!"
This will throw an error obviously as you didn't defined the test.hello
这显然会抛出错误,因为您没有定义 test.hello
Firstly you need to need define the hello key then inside you can assign any key. But if you want to create key if not exists then you can do following thing
首先你需要定义 hello 键,然后在里面你可以分配任何键。但是如果你想创建不存在的密钥,那么你可以做以下事情
test.hello = test.hello || {};
The above statement will create the test.hello object if not defined and if it is defined then it will assign the same value as it is previously
如果未定义,则上述语句将创建 test.hello 对象,如果已定义,则将分配与之前相同的值
Now you can assign any new key inside the test.hello
现在您可以在 test.hello 中分配任何新键
test.hello.world = "Everything works perfect";
test.hello.world2 = 'With another key too, it works perfect';
回答by Frederik.L
I've come up with something, really custom as well, but it works as far as I have tested.
我想出了一些东西,也确实是自定义的,但就我测试过的而言,它确实有效。
function dotted_put_var(str,val) {
var oper=str.split('.');
var p=window;
for (var i=0;i<oper.length-1;i++) {
var x=oper[i];
p[x]=p[x]||{};
p=p[x];
}
p[oper.pop()]=val;
}
Then, a complex variable can be set like this, ensuring that every links will be created if not already:
然后,可以像这样设置一个复杂的变量,确保如果还没有创建每个链接:
dotter_put_var('test.hello.world', 'testvalue'); // test.hello.world="testvalue";
See this working FIDDLE.
请参阅此工作FIDDLE。