Javascript 如何自动向未定义的对象添加属性?
如果对象不存在,是否有一种简单的方法可以自动向对象添加属性 考虑以下示例:Javascript 如何自动向未定义的对象添加属性?,javascript,Javascript,如果对象不存在,是否有一种简单的方法可以自动向对象添加属性 考虑以下示例: var test={} test.hello.world=“hello不存在!” 这不起作用,因为未定义hello 我问这个问题的原因是因为我有一些现有的对象,我不知道它们是否都准备好了hello。实际上,我在代码的不同部分中有很多这样的对象。 总是检查hello是否存在,以及是否没有创建新对象(如: var test={} 如果(test.hello==未定义)test.hello={} test.hello.wor
var test={}
test.hello.world=“hello不存在!”
这不起作用,因为未定义hello
我问这个问题的原因是因为我有一些现有的对象,我不知道它们是否都准备好了hello
。实际上,我在代码的不同部分中有很多这样的对象。
总是检查hello
是否存在,以及是否没有创建新对象(如:
var test={}
如果(test.hello==未定义)test.hello={}
test.hello.world=“hello world!”
在本例中,是否有一种方法可以自动创建像hello
这样的对象
我在php中的意思是类似的:
$test=array();
$test['hello']['world']=“hello world”;
var_dump($测试);
输出:
数组(1){
[“hello”]=>数组(1){
[“世界”]=>字符串(11)“你好,世界”
}
}
好的,这是一个数组,但在js数组中,这和对象的问题是一样的
var test = {};
test.hello = test.hello || {};
test.hello.world = "Hello world!";
如果test.hello
未定义,则将其设置为空对象
如果先前定义了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.
如果没有某种函数,您将无法做到这一点,因为JavaScript没有用于对象的通用getter/setter方法(例如,Python具有
\uuuuuu getattr\uuuu
)。这里有一种方法:
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;
}
如果确实需要,可以将其添加到对象的原型中。你可以这样称呼它:
> var o = {}
> add_property(o, 'foo.bar.baz', 12)
> o.foo.bar.baz
12
我已经想出了一些东西,真正的自定义以及,但它的工作,因为我已经测试
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;
}
查看此操作。这将向测试对象添加一个属性hello
,其值为{world:'hello world!'}
,如果该属性不存在。如果你有很多这样的对象,你可以迭代它们并应用这个函数。注:用途
这实际上是一个方便的说法:
var defaults = _.partialRight(_.assign, function(a, b) {
return typeof a == 'undefined' ? b : a;
});
defaults(test, { hello: {world: 'Hello world!'} });
注意:\默认值
使用循环实现与第二个块相同的功能
p.S.Checkout您可以使用返回属性的函数扩展对象的原型,但如果不存在,则首先添加属性:
Object.prototype.getOrCreate = function (prop) {
if (this[prop] === undefined) {
this[prop] = {};
}
return this[prop];
};
var obj = {};
obj.getOrCreate("foo").getOrCreate("bar").val = 1;
新对象
myObj = {};
递归函数
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;
}
用点符号字符串调用它
addProps(myObj, 'sub1.sub2.propA', 1);
或者使用数组
addProps(myObj, ['sub1', 'sub2', 'propA'], 1);
你的物体看起来像这样
myObj = {
"sub1": {
"sub2": {
"propA": 1
}
}
};
它也适用于非空对象 我用这个:
Object.prototype.initProperty = function(name, defaultValue) {
if (!(name in this)) this[name] = defaultValue;
};
您可以稍后执行f.e.:
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}
这将抛出一个错误,因为您没有定义测试。您好
test.hello.world = "Everything works perfect";
test.hello.world2 = 'With another key too, it works perfect';
首先你需要定义hello键,然后在里面你可以分配任何键。
但若你们想创建一个不存在的密钥,那个么你们可以做下面的事情
test.hello = test.hello || {};
上面的语句将创建test.hello对象(如果未定义),如果已定义,则将分配与以前相同的值
现在,您可以在测试中分配任何新密钥。hello
test.hello.world = "Everything works perfect";
test.hello.world2 = 'With another key too, it works perfect';
这是一个带有代理的酷版本:
const myUpsert = (input) => {
const handler = {
get: (obj, prop) => {
obj[prop] = obj[prop] || {};
return myUpsert(obj[prop]);
}
};
return new Proxy(input, handler);
};
你是这样使用它的:
myUpsert(test).hello.world = '42';
这会将所有缺少的属性添加为空对象,并保留现有属性不变。它实际上只是经典的test.hello=test.hello |{}
的一个代理版本,虽然速度要慢得多(.),但它看起来也更好,尤其是如果你要做一个以上的层次。我不会选择它进行高性能的数据处理,但它可能足够快,可以进行前端状态更新(如Redux)
请注意,这里有一些隐含的假设:
中间的属性要么是对象,要么不存在。例如,如果test.hello
是一个字符串,这将阻塞
只要您使用代理而不是原始对象,您就始终希望这样做
如果您仅在边界良好的上下文(如reducer body)中使用它,那么就很容易缓解这些问题,因为在这些上下文中,意外返回代理的可能性很小,而您不想对对象执行其他操作。
let test={};
test={…test,hello:{…test.hello,world:'hello确实存在!'};
控制台日志(测试)代码>我对进行了一些更改以允许创建阵列:
函数addProps(obj、arr、val){
if(typeof arr=='string')
arr=arr.split(“.”);
var tmpObj,isArray=/^(.*)\[(\d+)\]$/.exec(arr[0])
if(isArray&&!Number.isNaN(isArray[2])){
obj[isArray[1]]=obj[isArray[1]]| |[];
obj[isArray[1]][isArray[2]]=obj[isArray[1]][isArray[2]]]||{}
tmpObj=obj[isArray[1]][isArray[2]];
}否则{
obj[arr[0]]=obj[arr[0]]| |{};
tmpObj=obj[arr[0]];
}
如果(arr.length>1){
arr.shift();
addProps(tmpObj、arr、val);
}否则
obj[arr[0]]=val;
返回obj;
}
var myObj={}
addProps(myObj,'sub1[0]。sub2.propA',1)
addProps(myObj,'sub1[1]。sub2.propA',2)
console.log(myObj)
您可以使用逻辑空赋值(??=):
我认为最简单的方法是使用Lodash
\.set({},'a[0].b.c',4);
//=>{a:[{b:{c:4}}]}
函数existcheckthingy(x,y,z){if(x==未定义)x={};x.y=z;}用作existcheckthingy(test.hello,world,“hello不存在!”)@鲍比,那不行。它将在existcheckthingy
函数的范围内创建一个新对象x
,但该对象随后不会附加到test
对象。使用“类似数组”的表示法可以做得更好:existcheckthingy(a,x,y,z){if(a[x]==undefined)a[x]={};a[x][y]=z;}
可能的重复:@Jeff oops,忘记了:3考虑lodash'set',这是非常惯用的JSIt,非常感谢。但这仍然是一个手动检查。不可能没有吗?@MarcelGwerder不,这是最短的了。@MarcelGwerder:据我所知不是。@xbonez NB:没有“定义”-truthy。霍
test.hello.world = "Everything works perfect";
test.hello.world2 = 'With another key too, it works perfect';
const myUpsert = (input) => {
const handler = {
get: (obj, prop) => {
obj[prop] = obj[prop] || {};
return myUpsert(obj[prop]);
}
};
return new Proxy(input, handler);
};
myUpsert(test).hello.world = '42';
var test = {};
(test.hello ??= {}).world ??= "Hello doesn't exist!";