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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 09:03:29  来源:igfitidea点击:

Automatically create object if undefined

javascript

提问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 helloisn'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 helloor not. I actually have a lot of these objects in different parts of my code. It is very annoying to always check if helloexists 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 helloin 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.hellois undefined, it gets set to an empty object.

如果test.hello未定义,则将其设置为空对象。

If test.hellowas 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 Objectwith 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:

请注意,这里有一些隐含的假设:

  1. The intervening properties are either objects or non-existent. This will choke if test.hellois a string, for example.
  2. That you always want to be doing this for as long as you're using the Proxy instead of the original object.
  1. 中间属性要么是对象,要么不存在。test.hello例如,如果是字符串,这将阻塞。
  2. 只要您使用代理而不是原始对象,您就一直希望这样做。

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 hellowhose 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: _.defaultsuses loops to achieve the same thing as the second block.

注意:_.defaults使用循环来实现与第二个块相同的事情。

P.S. Checkout https://stackoverflow.com/a/17197858/1218080

PS 结帐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