it-swarm.asia

إنشاء كائن تلقائيًا إذا لم يتم تحديده

هل هناك طريقة سهلة لإضافة الخصائص تلقائيًا إلى الكائنات إذا لم تكن موجودة بالفعل؟

النظر في المثال التالي:

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

هذا لا يعمل لأنه لم يتم تعريف hello.

السبب في أنني أسأل هذا لأن لدي بعض الكائنات الموجودة التي لا أعرف ما إذا كانت جميعها تحتوي على hello أم لا. لدي بالفعل الكثير من هذه الأشياء في أجزاء مختلفة من الكود. من المزعج للغاية التحقق دائمًا من وجود hello وما إذا كان لا ينشئ كائنًا جديدًا مثل:

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

هل هناك طريقة لإنشاء كائن تلقائيًا مثل hello في هذا المثال؟

أعني شيئًا كهذا في php:

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

انتاج:

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

حسنًا ، إنها صفيف ، لكن في المصفوفات js ، تكون نفس المشكلة مع الكائنات.

54
Marcel Gwerder
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.
102
xbonez

كائن جديد

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

إنه يعمل مع أشياء غير فارغة أيضًا!

11
columbus

حسنًا ، يمكنك توسيع النموذج الأولي لـ Object مع دالة تُرجع خاصية ، ولكن تضيفها أولاً ، إذا لم تكن موجودة:

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

var obj = {};

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

لن تتمكن من القيام بذلك دون وجود نوع من الوظيفة ، حيث أن 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;
}

إذا كنت تريد حقًا ، فيمكنك إضافته إلى النموذج الأولي لـ Object. يمكنك تسميتها مثل:

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

إليك نسخة رائعة مع الوكلاء:

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).

لاحظ أن هناك بعض الافتراضات الضمنية هنا:

  1. الخصائص المتداخلة هي كائنات أو غير موجودة. سيخنق هذا إذا كانت test.hello عبارة عن سلسلة ، على سبيل المثال.
  2. أنك تريد دائمًا القيام بذلك طالما أنك تستخدم الوكيل بدلاً من الكائن الأصلي.

يمكن التخفيف من حدة هذه الأشياء بسهولة إذا كنت تستخدمها فقط في سياقات جيدة الحدود (مثل هيئة مختزِلة) حيث لا توجد فرصة كبيرة لإرجاع الوكيل عن طريق الخطأ ، وليس هناك الكثير الذي قد ترغب في فعله مع الكائن.

3
John Neuhaus

سيؤدي ذلك إلى إضافة خاصية hello التي تكون قيمتها {world: 'Hello world!'} إلى كائن الاختبار ، إذا لم تكن موجودة. إذا كان لديك الكثير من هذه الكائنات ، فيمكنك تكرارها وتطبيق هذه الوظيفة. ملاحظة: يستخدم lodash.js

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

وهي في الواقع وسيلة راحة للقول:

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

ملاحظة: _.defaults يستخدم الحلقات لتحقيق نفس الشيء مثل الكتلة الثانية.

ملاحظة Checkout https://stackoverflow.com/a/17197858/1218080

2
holographic-principle

لقد توصلت إلى شيء ، مخصص حقًا ، لكنه يعمل بقدر ما قمت باختباره.

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

بعد ذلك ، يمكن تعيين متغير معقد مثل هذا ، مما يضمن إنشاء كل الروابط إن لم يكن بالفعل:

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

انظر هذا العمل كمان .

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

سيؤدي هذا إلى ظهور خطأ بوضوح لأنك لم تحدد الاختبار

تحتاج أولاً إلى تحديد مفتاح الترحيب ثم يمكنك تعيين أي مفتاح بداخله. ولكن إذا كنت ترغب في إنشاء مفتاح إذا لم يكن موجودًا ، فيمكنك فعل الشيء التالي

test.hello = test.hello || {};

ستقوم العبارة أعلاه بإنشاء كائن test.hello إذا لم يتم تعريفه وإذا تم تعريفه ، فسوف تقوم بتعيين نفس القيمة كما كانت في السابق

الآن يمكنك تعيين أي مفتاح جديد داخل test.hello

test.hello.world = "Everything works perfect";

test.hello.world2 = 'With another key too, it works perfect';
1
VIKAS KOHLI
var test = {}
if(!test.hasOwnProperty('hello')) {
    test.hello = {};
}
test.hello.world = "Hello World!"
1
Shawn31313

انا استعمل هذا:

Object.prototype.initProperty = function(name, defaultValue) {
  if (!(name in this)) this[name] = defaultValue;
};

يمكنك القيام به لاحقا:

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}
0
Michal Politzer
let test = {};
test = {...test, hello: {...test.hello, world: 'Hello does exist!'}};
console.log(test);

عند استخدام معامل الانتشار ، يمكن أن تكون القيمة غير محددة ، وسوف تقوم تلقائيًا بإنشاء كائن.

0
Nick