Soru Undefined ise otomatik olarak nesne yarat


Varsa, nesnelerin özelliklerine otomatik olarak eklemenin kolay bir yolu var mı?

Aşağıdaki örneği göz önünde bulundurun:

var test = {}
test.hello.world = "Hello doesn't exist!"

Bu işe yaramıyor çünkü hello tanımlı değil.

Bunu sormamın sebebi, var olan bazı nesnelerim var. hello ya da değil. Aslında bu nesnelerin çoğunun kodumun farklı bölümlerinde var. Her zaman kontrol etmek çok sinir bozucu hello Varsa ve şu gibi yeni bir nesne oluşturmazsa:

var test = {}
if(test.hello === undefined) test.hello = {}
test.hello.world = "Hello World!"

Otomatik olarak bir nesne oluşturmak için bir yolu var mı hello bu örnekte?

Php'de böyle bir şey demek istiyorum:

$test = array();  
$test['hello']['world'] = "Hello world";   
var_dump($test);

Çıktı:

array(1) {
  ["hello"]=>
  array(1) {
    ["world"]=>
    string(11) "Hello world"
  }
}

Tamam bu bir dizidir, ancak js dizilerinde nesnelerle aynı problemdir.


43
2017-07-14 21:28


Menşei


işlevi mevcut denetim (x, y, z) {if (x === undefined) x = {}; x.y = z; } varolan varlık olarak kullanılan (test.hello, dünya, "Merhaba, yok!"); - bobbybee
@bobbybee Çalışmayacak. Yeni bir nesne yaratacak x kapsamında existcheckthingy işlevi, ancak bu daha sonra test nesne. "Dizi benzeri" gösterimini kullanarak daha iyisini yapabilirsiniz: existcheckthingy(a,x,y,z) { if (a[x] === undefined) a[x] = {}; a[x][y] = z;} - Jeff
Olası kopya: stackoverflow.com/questions/7069584/... - FSou1
@Jeff oops, bunu unuttu: 3 - bobbybee
lodash 'set' düşünün - Rene Wooller


Cevaplar:


var test = {};
test.hello = test.hello || {};
test.hello.world = "Hello world!";

Eğer test.hello undefined, boş bir nesneye ayarlanır.

Eğer test.hello Daha önce tanımlanmış, değişmeden kalır.

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.

86
2017-07-14 21:31



İyi düşünmek (: - Shawn31313
bu oldukça fazla deyimsiz JS - Alnitak
Bunun için çok teşekkürler. Ama yine de manuel bir kontrol. Muhtemelen olmaz mı? - Marcel Gwerder
@MarcelGwerder hayır, bu kadar kısa. - Alnitak
@MarcelGwerder: Bildiğim kadarıyla değil. - xbonez


Yeni nesne

myObj = {};

özyinelemeli fonksiyon

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;

}

Noktalı bir dize ile çağırın.

addProps(myObj, 'sub1.sub2.propA', 1);

ya da bir dizi ile

addProps(myObj, ['sub1', 'sub2', 'propA'], 1);

ve nesnen buna benzeyecek

myObj = {
  "sub1": {
    "sub2": {
      "propA": 1
    }
  }
};

Boş olmayan nesnelerle de çalışır!


9
2017-12-10 14:56



Bu aslında gerçekten düzgün çalışıyor ve nesneyi kırmadan doğru değeri günceller. - RozzA


Peki prototipini uzatabilirsin Object Bir özelliği döndüren bir işlevle, ancak, eğer mevcut değilse, önce ekler:

Object.prototype.getOrCreate = function (prop) {
    if (this[prop] === undefined) {
        this[prop] = {};
    }
    return this[prop];
};

var obj = {};

obj.getOrCreate("foo").getOrCreate("bar").val = 1;

5
2017-07-14 22:07



Bu büyük bir çözüm gibi görünüyor, ancak bir nedenden dolayı DataTables'ı kırıyor. Normalde iyi bir fikir olarak düşünülen nesne içselleri ile uğraşıyor mu? - Jason Lewis
Bu nedenle, yerel nesnelerin genişletilmesi kötü bir fikir olabilir, çünkü yöntemler çakışabilir. - Tschallacka


JavaScript'in bir nesne için genel bir alıcı / ayarlayıcı yöntemi olmadığı için bunu bir tür işlev olmadan gerçekleştiremezsiniz (örneğin, Python __getattr__). İşte bunu yapmanın bir yolu:

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;
}

Eğer gerçekten istiyorsan, onu prototipine ekleyebilirsin. Object. Bunu şöyle diyebilirsiniz:

> var o = {}
> add_property(o, 'foo.bar.baz', 12)
> o.foo.bar.baz
12

3
2017-07-14 21:42



Aynı nesne üzerinde tekrar tekrar kullanıldığında bu işlevle ilgili bir şey yanlıştır - RozzA
@RozzA: Bu hatayı yakaladığın için teşekkürler, şimdi düzeltildi. - Blender
@Blender gibi mülkün değerini okumak için bir olasılık var read_property(o, 'foo.bar.baz') 12 dönecek mi? bir özellik eklendikten sonra - Karthikeyan Vedi


Bu özellik ekleyecektir hello kimin değeri {world: 'Hello world!'} Varsa, test nesnesine. Bu nesnelerin çoğuna sahipseniz, sadece bunları tekrarlayabilir ve bu işlevi uygulayabilirsiniz. Not: kullanır lodash.js

var test = {};
_.defaults(test, { hello: {world: 'Hello world!'} });    

Hangi aslında söyleyerek için kolaylık bir yöntemdir:

var defaults = _.partialRight(_.assign, function(a, b) {
  return typeof a == 'undefined' ? b : a;
});        
defaults(test, { hello: {world: 'Hello world!'} });

Not: _.defaults İkinci blokla aynı şeyi elde etmek için döngüler kullanır.

Not; Çıkış yapmak https://stackoverflow.com/a/17197858/1218080


2
2017-07-14 21:55



_.set ({}, 'abcd', "asdf") '{"a": {"b": {"c": {"d": "asdf"}}}}' yi yaratacaktır. aradığı şeyden daha fazlası - Rene Wooller


var test = {}
if(!test.hasOwnProperty('hello')) {
    test.hello = {};
}
test.hello.world = "Hello World!"

1
2017-07-14 21:31





Ben de çok özel bir şey buldum, ama test ettiğim kadarıyla çalışır.

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;
}

Daha sonra, karmaşık bir değişken, bu şekilde ayarlanamaz;

dotter_put_var('test.hello.world', 'testvalue'); // test.hello.world="testvalue";

Bu çalışmayı gör KEMAN.


1
2017-07-14 21:42