Murrah
Murrah

Reputation: 1690

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

Upvotes: 29

Views: 25706

Answers (8)

hoshi
hoshi

Reputation: 1707

If you can use ES6, use the spread properties.

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

Upvotes: 59

M P
M P

Reputation: 265

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
}

Upvotes: 1

rob2d
rob2d

Reputation: 1166

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

Upvotes: 0

zzzzBov
zzzzBov

Reputation: 179046

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

Upvotes: 5

Blundering Philosopher
Blundering Philosopher

Reputation: 6805

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 }

Upvotes: 0

Tee
Tee

Reputation: 1

Below should work. I hope this help.

function create(includeB){

var object = {
    a: 1
};

if (includeB)
    object.b = 2;

return object;

}

Upvotes: 0

jfriend00
jfriend00

Reputation: 707238

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

Upvotes: 1

bozdoz
bozdoz

Reputation: 12860

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

Upvotes: 0

Related Questions