简体   繁体   中英

How to conditionally add properties to a javascript object literal

I am trying to do the following to satisfy the requirements of a code builder (Sencha Cmd to be specific).

This is the essence I what I need to do. The critical factor is that the function body MUST end with a return of an object literal. I cant return a variable due to restrictions in the builder. So, how to add a property 'b' at the point of the pseudo code below if the parameter 'includeB' is true, but NOT add a property AT ALL if it is false. ie b==undefined or b==null is not allowed.

Perhaps it is not possible.

function create(includeB) {
        // Can have code here but the final thing MUST be a return of the literal.
        // ...
    return {
        a : 1
        // pseudo code:
        // if (includeB==true) then create a property called b 
        // and assign a value of 2 to it. 
        // Must be done right here within this object literal
    }
}

var obj = create(false);
// obj must have property 'a' ONLY

var obj = create(true);
// obj must have properties 'a' and 'b'

Thanks for reading and considering,

Murray

If you can use ES6, use the spread properties .

function create(includeB) {
    return {
        a : 1,
        ...(includeB ? { b: 2 } : {}),
    };
}

You've pretty much shown a use case for a constructor function instead of using an object literal:

function CustomObject(includeB) {
    this.a = 1;
    if (includeB) {
        this.b = 2;
    }
}

//has `a` only
var obj1 = new CustomObject(false);

//has `a` and `b`
var obj2 = new CustomObject(true);

After re-reading your question it appears that you've got limited access in modifying the function. If I'm understanding your question correctly you can only change a limited portion of the script:

function create(includeB) {
    // modifications may be done here

    // the rest may not change
    return {
        a : 1
    }
}

var obj = create(false);
// obj must have property 'a' ONLY

var obj = create(true);
// obj must have properties 'a' and 'b'

If that's the case, then you could simply skip the later part of the function:

function create(includeB) {
    if (includeB) {
        return {
            a: 1,
            b: 2
        };
    }
    return {
        a: 1
    };
}

You cannot put boolean logic inside a javascript literal definition. So, if your builder requires the the returned object can ONLY be defined as a javascript literal, then you cannot define properties conditionally that way.


If you can create an object inside your function, modify that object using logic and then return that object, then that's pretty easy.

function create(includeB) {
    var x = {
        a: 1
    };
    if (includeB) {
        x.b = 2;
    }
    return x;
}

Your other option would be to wrap the create function and do it outside the create function.

function myCreate(includeB) {
    var x = create(includeB)
    if (includeB) {
        x.b = 2;
    }
    return x;
}

Or, you could even wrap the create function transparently so callers still use create() , but it's behavior has been altered.

var oldCreate = create;
create = function(includeB) {
    var x = oldCreate(includeB);
    if (includeB) {
        x.b = 2;
    }
    return x;
}

This should work exactly how you want:

const obj = {
    a: 1,
    b: includeB ? 2 : undefined
}

I recently had to do this, and found you could use a self-calling function within an object's definition (if using ES6). This is similar to the accepted answer, but might be useful for others who need to do this without first defining a constructor function.

For example:

let obj = (() => {
  let props = { a: 1 };
  if ( 1 ) props.b = 2;
  return props;
})();

makes the object: { a: 1, b: 2 }

It's handy for more complicated objects, keeping the construction continuous:

let obj = {
  a: 1,
  b: (() => {
    let props = { b1: 1 };
    if ( 1 ) props.b2 = 2;
    return props;
    })(),
  c: 3
}

makes the object:

{
  a: 1,
  b: {
    b1: 1,
    b2: 2
  },
  c: 3
}

You could define it later:

var hasA = create(); // has hasA.a

var hasBoth = create();
hasBoth.b = 2; //now has both

Alternatively, using your argument in create :

function create (includeB) {
  var obj = { 
    a : 1
  };
  if (includeB) {
     obj.b = 2;
  }
  return obj;
}

How about this:

function create(includeB) {
    return includeB && { a:1, b:2 } || { a:1 };
}

When includeB is true, the create function will return {a:1, b:2} . If includeB is false, it will return whatever is after the or - in this case, the {a:1} object.

create(true) returns { a:1, b:2 } .

create(false) returns { a:1 }

Below should work. I hope this help.

function create(includeB){

var object = {
    a: 1
};

if (includeB)
    object.b = 2;

return object;

}

If you would like to use a declaration to satisfy the same requirement once without too much bloat, you can also simply do the following:

var created = function(includeB) {
    var returnObj = { a : 1 };

    if(includeB) { returnObj.b = 2; }

    return returnObj;
}}(); //automatically runs and assigns returnObj to created

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM