Reputation: 660
EDIT: Made clearer that the need is to determine if I can add properties to a value, not if a value can have its own properties.
Is there a way to check if is possible to add properties to a value
?
For example, if I have this code:
function test( value ) {
// return true if it is possible to add properties to value
}
Other than actually adding a property value
to test, is there a reliable way to deduce if value
is something that properties can be added to?
For example, I know an object
can have properties and undefined
can't, but I'm not keen on creating a list of known things that might not suffice in the future. Is something like instanceof object
sufficient?
Upvotes: 4
Views: 73
Reputation: 660
As pointed out by Jonas Wilms:
Bad usecase. You are just writing your next headache :)
I need to refactor my code so it doesn't need to jump through hoops.
Upvotes: 0
Reputation: 138557
The list of values that do not have properties is quite short: undefined
and null
. Testing for those should be straightforward (value == null
).
Note that all other primitives can have properties (through boxing), but as the boxed object gets lost immeadiately there is no sense in adding properties to them:
1..test = 1;
"test".test = 1;
Infinity.test = 1;
NaN.test = 1;
true.test = 1;
Symbol().test = 1;
1n.test = 1;
To check for non-primitives, typeof value === "object"
can be used, but as null
is also an object (a very special one, actually it counts as a primitive but typeof
lies about that), you have to explicitly check for value !== null
.
While you can usually add properties to objects, they can be frozen, then adding properties is useless, the same applies to Proxies.
const obj = {};
Object.freeze(obj);
obj.test = 1;
console.log(obj.test);
And as Proxies can't be detected, there is no way to find out wether a property can be added or not.
Upvotes: 4
Reputation: 42054
A simple idea (although it does not solve completely the case as per Jonas Wilms answer) may be:
function test(value) {
try {
if (value.p === undefined) {
value.p = 10;
if (value.p === undefined) {
return false;
}
delete value.p;
}
} catch(e) {
return false;
}
return true;
}
console.log('null: ' + test(null));
console.log('undefined: ' + test(undefined));
console.log('number: ' + test(10));
console.log('object: ' + test({a:10}));
var obj = { get p() { return false; }, set p(v) {} };
console.log('object with property name confict: ' + test(obj));
Upvotes: 0