We can create "Enums" in Javascript as follows:
var MyEnum = {
A: 0,
B: 1,
}
Can I use empty objects instead of numbers as follows?
var MyEnum = {
A: {},
B: {},
}
What's the difference and which should be used? There isn't any specific use case.
I changed my answer after you edited because just noticed what you are trying.
Yes you can use objects as enum value without any problem. When you define {} in an object, it creates and empty object with unique reference.
{} != {} won't be equal because two different objects with same doesn't mean they are same object. Two red balls you have, these balls are the same ball? No.
But instance.type == MyEnum.ObjectEnum1 will always be true.
Because both instance and the MyEnum object shares the same reference to the object.
var MyEnum = {
A: 1,
B: 2,
C: 3,
ObjectEnum1: {},
ObjectEnum2: {}
}
var obj1 = {
type: MyEnum.B
}
var obj2 = {
type: MyEnum.C
}
var obj3 = {
type: MyEnum.ObjectEnum1
}
console.log(obj1.type == MyEnum.B); //Should be true
console.log(obj2.type == MyEnum.A); //Should be false
console.log(obj2.type == MyEnum.C); //Should be true
console.log(obj3.type == MyEnum.ObjectEnum1); //Should be true
console.log(obj3.type == MyEnum.ObjectEnum2); //Should be false
Related
I have an object
const a = {
b: {
c: "new object",
b: {
c: "new object",
}
}
}
Here, the level of nesting for the key b is 2. I want to add another
b: {
c: "new object",
}
to the last b i.e., 2nd level nested b which will make the object now have 3 level of nested b
The level of nesting is dynamic. It can be 0 as well. That means const a = {}
How can add an object to a nested object, knowing the level of nesting?
eval() is out of option.
I'm currently doing it with lodash.
let currentObj = a;
const thePath = ["b"];
// checking if "b" is present in the object and nesting if present
while (currentObj["b"]) {
currentObj = currentObj["b"];
thePath.push("b");
}
lodash.set(a, thePath, {
c: "new object"
});
Is there any other approach? Can it be achieved with Object.assign somehow?
You could iterate the object and get finally the target object.
const object = { b: { b: { l: 2 }, l: 1 }, l: 0 };
let temp = object,
depth = 2;
while (depth--) temp = temp.b;
console.log(temp);
Object.assign(temp, { payload: 'foo' });
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Even without Object.assign I was able to make it work.
let currentObj = a;
const thePath = ["b"];
// checking if "b" is present in the object and nesting if present
while (currentObj["b"]) {
currentObj = currentObj["b"];
}
currentObj["b"] = {
c: "new object"
}
);
destructuring assignment doesn't work for the field in one object holds a falsy value, as follow:
let { aaa = 123 } = { aaa: null }
console.log(aaa) // null
so, how to achive ||= in object destructuring assignment to implement such the field's destructed defalut value ? like this:
let { aaa ||= 123 } = { aaa: null }
console.log(aaa) // 123
// it equals to
// let aaa = ({ aaa: null }).aaa || 123
You can add a default value in this way
let obj = null
{ obj1 } = { obj1: obj || 123 }
OR
try assigning values to an object using a constructor. In that way the destructuring would work fine:
class Obj1 {
a: string
b: number
constructor(obj) {
this.a = obj && obj.a || 'default a'
this.b = obj && obj.b || 1
}
}
let obj = null
let obj1 = new Obj1(obj)
let {aaa} = {aaa: obj1}
So you cannot do what you are trying to do.
The destructuring assignment works as expected/specified. It is just that the default value only works when the destructured value is undefined.
You have to use the normal syntax for "falsy" values (note: this includes undefined, false, 0, NaN etc. Extensive list at https://developer.mozilla.org/en-US/docs/Glossary/Falsy).
let { aaa } = { aaa: null }
aaa ||= 123;
Quoting from MDN Destructuring assignment
for objects
Default values
A variable can be assigned a default, in the case that the value unpacked from the object is undefined.
for arrays
Default values
A variable can be assigned a default, in the case that the value unpacked from the array is undefined.
There are already a lot of cool features in ES6/ES7 for defining Javascript objects. However, the following pattern is common in Javascript:
const obj = {
requiredKey1: ...,
requiredKey2: ...
};
if (someCondition) {
obj.optionalKey1 = ...;
}
Is there a way to define the object all at once with both optional and required keys?
You can use object spread to have an optional property:
let flag1 = true;
let flag2 = false;
const obj = {
requiredKey1: 1,
requiredKey2: 2,
...(flag1 && { optionalKey1: 5 }),
...(flag2 && { optionalKey2: 6, optionalKey3: 7 }),
...(flag1 && { optionalKey4: 8, optionalKey5: 9 })
};
console.log(obj);
To indicate optional key, you can assign to it null, if the condition is false
const someCondition = true;
const obj = {
requiredKey1: 1,
requiredKey2: 2,
optionalKey1: someCondition ? 'optional' : null
};
console.log(obj);
the following pattern is common in Javascript
It should not. Having many objects of different shapes can incur a performance penalty. Records should always contain the same keys. So just use
const obj = {
requiredKey1: …,
requiredKey2: …,
optionalKey1: someCondition ? … : undefined,
};
This question already has answers here:
What's the correct way to test for existence of a property on a JavaScript Object?
(3 answers)
Closed 6 years ago.
I want to look through an object and assign each of it's existent properties to a variable.
There are 4 possible properties. Some of the objects have all 4. Some might only have two.
How can I check if a particular property exists? Is there an equivalent of indexOf() for arrays but for objects instead?
Use the in keyword:
"key" in object
which returns true or false, depending if the object, or anything in its prototype chain, has that property.
You can also use object.hasOwnProperty("key"), which will only be true if the object has key as a property of itself, not its prototype. Example:
var object = {};
"toString" in object; // true
object.hasOwnProperty("toString"); // false
Note (as per #dandavis's comment) that if object has a custom property called hasOwnProperty, this gets thwarted; to work around this, use hasOwnProperty.call(object, "key"). Example:
var a = {hasOwnProperty: Boolean};
a.hasOwnProperty('name'); // true
hasOwnProperty.call(a, 'name'); // false
If you are only interested in properties set directly on the object (not accessible via the prototype chain) then hasOwnProperty will provide a boolean value, true, if an object has the specified property.
For example: testObject.hasOwnProperty('propertyToCheckFor') would return true if testObject.propertyToCheckFor exists, otherwise it would be false.
See the following code for a more expanded example:
var obj1 = {
a: 1
};
var obj2 = {
a: 1,
b: 2
};
var obj3 = {
b: 2,
c: 3
};
var obj4 = {
a: 1,
b: 2,
c: 3
};
// For dispaly purposes
document.write('<pre>' + JSON.stringify({
obj1: {
hasA: obj1.hasOwnProperty('a'),
hasB: obj1.hasOwnProperty('b'),
hasC: obj1.hasOwnProperty('c')
},
obj2: {
hasA: obj2.hasOwnProperty('a'),
hasB: obj2.hasOwnProperty('b'),
hasC: obj2.hasOwnProperty('c')
},
obj3: {
hasA: obj3.hasOwnProperty('a'),
hasB: obj3.hasOwnProperty('b'),
hasC: obj3.hasOwnProperty('c')
},
obj4: {
hasA: obj4.hasOwnProperty('a'),
hasB: obj4.hasOwnProperty('b'),
hasC: obj4.hasOwnProperty('c')
}
}, null, 2) + '</pre>');
var obj = {
foo: 1,
bar: 2,
baz: 3
}
Object.keys(obj).forEach(function(key) {
window[key] = obj[key]
})
console.log(foo, bar, baz)
Or in ES2015
const obj = {
foo: 1,
bar: 2,
baz: 3
}
function assignPrivateVars() {
let {foo, bar, baz} = obj;
console.log(foo, bar, baz);
}
assignPrivateVars();
You can use destructuring assignment. If value is not defined, variable will be set to undefined. You can also check if variable is defined after destructuring then delete variable by reference.
var data = {a:1, b:2, c:3};
var {a, b, c, d} = data; // `d`: `undefined`
Assume code of the following kind (e.g. using lodash or explicitly like here):
function extend(base, overwrite) {
for (var key in overwrite)
base[key] = overwrite[key];
return base;
}
var first = extend({
a: 1
}, {
b: 2
});
var second = extend({
c: 3
}, {
d: 4
});
console.log(first.a + first.b + second.c + second.d);
How can I explain to Flowtype that this is actually fine?
Try putting this just above function declaration:
declare function extend<A, B>(a: A, b: B): A & B