0

I want to set the property of object to something if condition is true, else do nothing.

And I tried to use ? operator by

obj.prop = (...)?sth:null;

and

obj.prop = (...)?sth:undefined;

But it turns out that nether one of them can perform what I want.

Given the condition is false, when I called obj.hasOwnProperty(prop), it always gives me true.

Is there a way to do it?

I know I can do it by using if syntax but I just want to know if I can do the same thing using ? operator.

try-catch-finally
  • 7,436
  • 6
  • 46
  • 67
Henry Hung
  • 35
  • 1
  • 8

2 Answers2

1

When you assign a property like this:

var obj = {
    a : undefined // or any other value
};

this happens according to the ECMAScript spec:

11.1.5 Object Initialiser

[...]

The production PropertyNameAndValueList : PropertyAssignment is evaluated as follows:

  1. Let obj be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name.
  2. Let propId be the result of evaluating PropertyAssignment.
  3. Call the [[DefineOwnProperty]] internal method of obj with arguments propId.name, propId.descriptor, and false.
  4. Return obj.

When you assign a property like this:

obj.a = undefined;

this happens according to the ECMAScript spec:

8.12.5 [[Put]] ( P, V, Throw )

[...]

  1. Else, create a named data property named P on object O as follows a. Let newDesc be the Property Descriptor {[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}. b. Call the [[DefineOwnProperty]] internal method of O passing P, newDesc, and Throw as arguments.

In either case, since undefined and null are legimite values, this will just define the property with this value.

Finally, hasOwnProperty() will only check if a property descriptor was created, the value does not matter:

15.2.4.5 Object.prototype.hasOwnProperty (V)

[...]

  1. Let desc be the result of calling the [[GetOwnProperty]] internal method of O passing P as the argument.
  2. If desc is undefined, return false.
  3. Return true.

But, according to the ECMAScript spec, both a property set to undefined and a not set property, will return undefined if you access them:

8.12.3 [[Get]] (P)

[...]

  1. If desc is undefined, return undefined.
  2. If IsDataDescriptor(desc) is true, return desc.[[Value]].
  3. Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be desc.[[Get]].
  4. If getter is undefined, return undefined.
  5. Return the result calling the [[Call]] internal method of getter providing O as the this value and providing no arguments.

Proof:

var obj = {
  a : undefined
}

console.log(typeof obj.a); // undefined
console.log(typeof obj.b); // undefined
obj.hasOwnProperty('a') // true
obj.hasOwnProperty('b') // false

Only delete will remove the property.

var obj = {
  a : null,
  b : undefined
}

obj.hasOwnProperty('a') // true
obj.hasOwnProperty('b') // true

delete obj.a;
delete obj.b;

obj.hasOwnProperty('a') // false
obj.hasOwnProperty('b') // false

Reading the ECMAScript spec on delete is left to the reader.

try-catch-finally
  • 7,436
  • 6
  • 46
  • 67
t.niese
  • 39,256
  • 9
  • 74
  • 101
  • I think Henry is trying to set it to some value , not trying to delete/remove the prop – Sujith Jul 19 '17 at 04:37
  • @Sujith `[...]Given the condition is false, when I called obj.hasOwnProperty(prop), it always gives me true.[...]`. If the condition is `false` the OP assigns `null` or `undefined`, but that would not change `obj.hasOwnProperty('prop')` to `false` it will still stay `true`. – t.niese Jul 19 '17 at 04:39
  • so by using ? : operator, prop is created no matter condition is true or false. Right? – Henry Hung Jul 19 '17 at 04:39
  • @HenryHung yes it will always create a property. Because you will always assign the result of your `?:` expression to `obj.prop`. – t.niese Jul 19 '17 at 04:40
  • 1
    @t.niese: updated your answer to reference the ECMAScript spec on the relevant cases. Obviously the inner workings of `[[Put]]` and `hasOwnProperty()` was unclear to the TO, so I though it would be nice to elaborate a bit more on that. I hope you like the edit, if you don't: just revert it. – try-catch-finally Jul 19 '17 at 20:10
0

Assuming that the result of your condition is falsy enough, something like this should work. All falsey values in JavaScript

var obj = {

  a: true,
  b: false,

}

obj.prop1 = obj.a ? true : false;
obj.prop2 = obj.b ? true : false;

console.log(obj);
trevdev
  • 241
  • 2
  • 12