ECMAScript 5: Why are some property attributes inherited while others are not? - javascript

It appears that ECMAScript 5 property attributes are inherited while others are not. Based on a simple experiment in Google Chrome, Safari, and Firefox, it seems that enumerable and writable are inherited from prototypes, but configurable is not. Consider when a is the prototype of b, and a defines property x (but b does not). If x is not writable, then b cannot override the value of x with =, which would, if allowed, only change b's x, and not a's (which is the x marked as non-writable). However, even if x is neither configurable nor writable, b may override the value of x with Object.defineProperty(b, 'x', ...) (which would fail for a: Object.defineProperty(a, 'x', ...), because a's `x' is not configurable).
I don't see anything in the standard that explains this (perhaps it's there, but I can't find it). Is this inconsistent behaviour intended?
Test output (answers "do a's and b's property attribute behave the same way?):
Object {enumerable: true, configurable: false, writable: true}
Code used to test:
function isEnumerable(p, o) {
for (var key in o) {
if (key === p) {
return true;
}
return false;
}
}
function isConfigurable(p, d, o) {
try {
Object.defineProperty(o, p, d);
return true;
} catch (e) {
return false;
}
}
function isWritable(p, v, o) {
if (o[p] === v) {
throw 'Error: isWritable will not work with identical value';
}
o[p] = v;
return o[p] === v;
}
function inheritedAttributes(
parentGenerator,
propertyName,
differentDescriptor,
differentValue) {
var parent, child, rtn = {};
var fns = {
'enumerable': isEnumerable.bind(this, propertyName),
'configurable': isConfigurable.bind(
this,
propertyName,
differentDescriptor),
'writable': isWritable.bind(this, propertyName, differentValue)
};
for (var key in fns) {
parent = parentGenerator();
child = Object.create(parent);
rtn[key] = fns[key](parent) === fns[key](child);
}
return rtn;
}
var propertyName = 'x';
var starterProperties = {};
starterProperties[propertyName] = {
'writable': false,
'configurable': false,
'enumerable': false,
'value': 'foo'
};
var differentDescriptor = {
'writable': false,
'configurable': false,
'enumerable': false,
'value': 'bar'
};
var differentValue = 'baz';
var parentGenerator = function() {
return Object.create(Object.prototype, starterProperties);
};
window.console.log(inheritedAttributes(
parentGenerator,
propertyName,
differentDescriptor,
differentValue
));

This doesn't answer "why". I suspect the answer to "why" is, "because that's what the standard says". Nevertheless, here are some relevant links, excerpts, and paraphrases from the standard. Thanks to basilikum for pointing me in the right direction.
Enumerable
for (var key in obj) { ... }
The for-in statement documentation states (emphasis added):
Enumerating the properties of an object includes enumerating
properties of its prototype, and the prototype of the prototype, and
so on, recursively; but a property of a prototype is not enumerated if
it is “shadowed” because some previous object in the prototype chain
has a property with the same name. The values of [[Enumerable]]
attributes are not considered when determining if a property of a
prototype object is shadowed by a previous object on the prototype
chain.
Hence, enumerability is inherited.
Writable
obj.x = a;
Property assignment invokes the internal method [[Put]], which starts by checking the return value of [[CanPut]]. When the property is a value, not a getter+setter, [[CanPut]] will check property attributes in the following order:
obj's x property's writable attribute
obj's extensible attribute
For each prototype from obj's prototype down to (but not including) null:
prototype's extensible attribute
prototype's x property's writable attribute
If any of these attributes is defined, then its value is returned. Hence, even when other attributes are missing, a non-writable property somewhere down obj's prototype chain causes assignment to fail on obj; i.e., writability is inherited.
Configurable
Object.defineProperty(obj, 'x', { 'value': a, ... });
Object.defineProperty invokes the internal method [[DefineOwnProperty]], which is rather convoluted. In general, this method will concern itself only with the extensible attribute of obj, and the configurable attribute of obj's current own x property, if it exists. As such, a non-configurable property, x, somewhere down obj's prototype chain does not influence this procedure; i.e., configurability is not inherited.

Related

How to return an Object Value if you have a specific key in your Object? [duplicate]

How do I check if an object has a specific property in JavaScript?
Consider:
x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
//Do this
}
Is that the best way to do it?
2022 UPDATE
Object.hasOwn()
Object.hasOwn() is recommended over Object.hasOwnProperty() because it works for objects created using Object.create(null) and with objects that have overridden the inherited hasOwnProperty() method. While it is possible to workaround these problems by calling Object.prototype.hasOwnProperty() on an external object, Object.hasOwn() is more intuitive.
Example
const object1 = {
prop: 'exists'
};
console.log(Object.hasOwn(object1, 'prop'));
// expected output: true
Original answer
I'm really confused by the answers that have been given - most of them are just outright incorrect. Of course you can have object properties that have undefined, null, or false values. So simply reducing the property check to typeof this[property] or, even worse, x.key will give you completely misleading results.
It depends on what you're looking for. If you want to know if an object physically contains a property (and it is not coming from somewhere up on the prototype chain) then object.hasOwnProperty is the way to go. All modern browsers support it. (It was missing in older versions of Safari - 2.0.1 and older - but those versions of the browser are rarely used any more.)
If what you're looking for is if an object has a property on it that is iterable (when you iterate over the properties of the object, it will appear) then doing: prop in object will give you your desired effect.
Since using hasOwnProperty is probably what you want, and considering that you may want a fallback method, I present to you the following solution:
var obj = {
a: undefined,
b: null,
c: false
};
// a, b, c all found
for ( var prop in obj ) {
document.writeln( "Object1: " + prop );
}
function Class(){
this.a = undefined;
this.b = null;
this.c = false;
}
Class.prototype = {
a: undefined,
b: true,
c: true,
d: true,
e: true
};
var obj2 = new Class();
// a, b, c, d, e found
for ( var prop in obj2 ) {
document.writeln( "Object2: " + prop );
}
function hasOwnProperty(obj, prop) {
var proto = obj.__proto__ || obj.constructor.prototype;
return (prop in obj) &&
(!(prop in proto) || proto[prop] !== obj[prop]);
}
if ( Object.prototype.hasOwnProperty ) {
var hasOwnProperty = function(obj, prop) {
return obj.hasOwnProperty(prop);
}
}
// a, b, c found in modern browsers
// b, c found in Safari 2.0.1 and older
for ( var prop in obj2 ) {
if ( hasOwnProperty(obj2, prop) ) {
document.writeln( "Object2 w/ hasOwn: " + prop );
}
}
The above is a working, cross-browser, solution to hasOwnProperty(), with one caveat: It is unable to distinguish between cases where an identical property is on the prototype and on the instance - it just assumes that it's coming from the prototype. You could shift it to be more lenient or strict, based upon your situation, but at the very least this should be more helpful.
With Underscore.js or (even better) Lodash:
_.has(x, 'key');
Which calls Object.prototype.hasOwnProperty, but (a) is shorter to type, and (b) uses "a safe reference to hasOwnProperty" (i.e. it works even if hasOwnProperty is overwritten).
In particular, Lodash defines _.has as:
function has(object, key) {
return object ? hasOwnProperty.call(object, key) : false;
}
// hasOwnProperty = Object.prototype.hasOwnProperty
You can use this (but read the warning below):
var x = {
'key': 1
};
if ('key' in x) {
console.log('has');
}
But be warned: 'constructor' in x will return true even if x is an empty object - same for 'toString' in x, and many others. It's better to use Object.hasOwn(x, 'key').
Note: the following is nowadays largely obsolete thanks to strict mode, and hasOwnProperty. The correct solution is to use strict mode and to check for the presence of a property using obj.hasOwnProperty. This answer predates both these things, at least as widely implemented (yes, it is that old). Take the following as a historical note.
Bear in mind that undefined is (unfortunately) not a reserved word in JavaScript if you’re not using strict mode. Therefore, someone (someone else, obviously) could have the grand idea of redefining it, breaking your code.
A more robust method is therefore the following:
if (typeof(x.attribute) !== 'undefined')
On the flip side, this method is much more verbose and also slower. :-/
A common alternative is to ensure that undefined is actually undefined, e.g. by putting the code into a function which accepts an additional parameter, called undefined, that isn’t passed a value. To ensure that it’s not passed a value, you could just call it yourself immediately, e.g.:
(function (undefined) {
… your code …
if (x.attribute !== undefined)
… mode code …
})();
if (x.key !== undefined)
Armin Ronacher seems to have already beat me to it, but:
Object.prototype.hasOwnProperty = function(property) {
return this[property] !== undefined;
};
x = {'key': 1};
if (x.hasOwnProperty('key')) {
alert('have key!');
}
if (!x.hasOwnProperty('bar')) {
alert('no bar!');
}
A safer, but slower solution, as pointed out by Konrad Rudolph and Armin Ronacher would be:
Object.prototype.hasOwnProperty = function(property) {
return typeof this[property] !== 'undefined';
};
Considering the following object in Javascript
const x = {key: 1};
You can use the in operator to check if the property exists on an object:
console.log("key" in x);
You can also loop through all the properties of the object using a for - in loop, and then check for the specific property:
for (const prop in x) {
if (prop === "key") {
//Do something
}
}
You must consider if this object property is enumerable or not, because non-enumerable properties will not show up in a for-in loop. Also, if the enumerable property is shadowing a non-enumerable property of the prototype, it will not show up in Internet Explorer 8 and earlier.
If you’d like a list of all instance properties, whether enumerable or not, you can use
Object.getOwnPropertyNames(x);
This will return an array of names of all properties that exist on an object.
Reflections provide methods that can be used to interact with Javascript objects. The static Reflect.has() method works like the in operator as a function.
console.log(Reflect.has(x, 'key'));
// expected output: true
console.log(Reflect.has(x, 'key2'));
// expected output: false
console.log(Reflect.has(object1, 'toString'));
// expected output: true
Finally, you can use the typeof operator to directly check the data type of the object property:
if (typeof x.key === "undefined") {
console.log("undefined");
}
If the property does not exist on the object, it will return the string undefined. Else it will return the appropriate property type. However, note that this is not always a valid way of checking if an object has a property or not, because you could have a property that is set to undefined, in which case, using typeof x.key would still return true (even though the key is still in the object).
Similarly, you can check if a property exists by comparing directly to the undefined Javascript property
if (x.key === undefined) {
console.log("undefined");
}
This should work unless key was specifically set to undefined on the x object
Let's cut through some confusion here. First, let's simplify by assuming hasOwnProperty already exists; this is true of the vast majority of current browsers in use.
hasOwnProperty returns true if the attribute name that is passed to it has been added to the object. It is entirely independent of the actual value assigned to it which may be exactly undefined.
Hence:
var o = {}
o.x = undefined
var a = o.hasOwnProperty('x') // a is true
var b = o.x === undefined // b is also true
However:
var o = {}
var a = o.hasOwnProperty('x') // a is now false
var b = o.x === undefined // b is still true
The problem is what happens when an object in the prototype chain has an attribute with the value of undefined? hasOwnProperty will be false for it, and so will !== undefined. Yet, for..in will still list it in the enumeration.
The bottom line is there is no cross-browser way (since Internet Explorer doesn't expose __prototype__) to determine that a specific identifier has not been attached to an object or anything in its prototype chain.
If you are searching for a property, then "no". You want:
if ('prop' in obj) { }
In general, you should not care whether or not the property comes from the prototype or the object.
However, because you used 'key' in your sample code, it looks like you are treating the object as a hash, in which case your answer would make sense. All of the hashes keys would be properties in the object, and you avoid the extra properties contributed by the prototype.
John Resig's answer was very comprehensive, but I thought it wasn't clear. Especially with when to use "'prop' in obj".
For testing simple objects, use:
if (obj[x] !== undefined)
If you don't know what object type it is, use:
if (obj.hasOwnProperty(x))
All other options are slower...
Details
A performance evaluation of 100,000,000 cycles under Node.js to the five options suggested by others here:
function hasKey1(k,o) { return (x in obj); }
function hasKey2(k,o) { return (obj[x]); }
function hasKey3(k,o) { return (obj[x] !== undefined); }
function hasKey4(k,o) { return (typeof(obj[x]) !== 'undefined'); }
function hasKey5(k,o) { return (obj.hasOwnProperty(x)); }
The evaluation tells us that unless we specifically want to check the object's prototype chain as well as the object itself, we should not use the common form:
if (X in Obj)...
It is between 2 to 6 times slower depending on the use case
hasKey1 execution time: 4.51 s
hasKey2 execution time: 0.90 s
hasKey3 execution time: 0.76 s
hasKey4 execution time: 0.93 s
hasKey5 execution time: 2.15 s
Bottom line, if your Obj is not necessarily a simple object and you wish to avoid checking the object's prototype chain and to ensure x is owned by Obj directly, use if (obj.hasOwnProperty(x))....
Otherwise, when using a simple object and not being worried about the object's prototype chain, using if (typeof(obj[x]) !== 'undefined')... is the safest and fastest way.
If you use a simple object as a hash table and never do anything kinky, I would use if (obj[x])... as I find it much more readable.
Yes it is :) I think you can also do Object.prototype.hasOwnProperty.call(x, 'key') which should also work if x has a property called hasOwnProperty :)
But that tests for own properties. If you want to check if it has an property that may also be inhered you can use typeof x.foo != 'undefined'.
if(x.hasOwnProperty("key")){
// …
}
because
if(x.key){
// …
}
fails if x.key is falsy (for example, x.key === "").
You can also use the ES6 Reflect object:
x = {'key': 1};
Reflect.has( x, 'key'); // returns true
Documentation on MDN for Reflect.has can be found here.
The static Reflect.has() method works like the in operator as a function.
Do not do this object.hasOwnProperty(key)). It's really bad because these methods may be shadowed by properties on the object in question - consider { hasOwnProperty: false } - or, the object may be a null object (Object.create(null)).
The best way is to do Object.prototype.hasOwnProperty.call(object, key) or:
const has = Object.prototype.hasOwnProperty; // Cache the lookup once, in module scope.
console.log(has.call(object, key));
/* Or */
import has from 'has'; // https://www.npmjs.com/package/has
console.log(has(object, key));
OK, it looks like I had the right answer unless if you don't want inherited properties:
if (x.hasOwnProperty('key'))
Here are some other options to include inherited properties:
if (x.key) // Quick and dirty, but it does the same thing as below.
if (x.key !== undefined)
Another relatively simple way is using Object.keys. This returns an array which means you get all of the features of an array.
var noInfo = {};
var info = {something: 'data'};
Object.keys(noInfo).length //returns 0 or false
Object.keys(info).length //returns 1 or true
Although we are in a world with great browser support. Because this question is so old I thought I'd add this:
This is safe to use as of JavaScript v1.8.5.
JavaScript is now evolving and growing as it now has good and even efficient ways to check it.
Here are some easy ways to check if object has a particular property:
Using hasOwnProperty()
const hero = {
name: 'Batman'
};
hero.hasOwnProperty('name'); // => true
hero.hasOwnProperty('realName'); // => false
Using keyword/operator in
const hero = {
name: 'Batman'
};
'name' in hero; // => true
'realName' in hero; // => false
Comparing with undefined keyword
const hero = {
name: 'Batman'
};
hero.name; // => 'Batman'
hero.realName; // => undefined
// So consider this
hero.realName == undefined // => true (which means property does not exists in object)
hero.name == undefined // => false (which means that property exists in object)
For more information, check here.
hasOwnProperty "can be used to determine whether an object has the specified property as a direct property of that object; unlike the in operator, this method does not check down the object's prototype chain."
So most probably, for what seems by your question, you don't want to use hasOwnProperty, which determines if the property exists as attached directly to the object itself,.
If you want to determine if the property exists in the prototype chain, you may want to use it like:
if (prop in object) { // Do something }
You can use the following approaches-
var obj = {a:1}
console.log('a' in obj) // 1
console.log(obj.hasOwnProperty('a')) // 2
console.log(Boolean(obj.a)) // 3
The difference between the following approaches are as follows-
In the first and third approach we are not just searching in object but its prototypal chain too. If the object does not have the property, but the property is present in its prototype chain it is going to give true.
var obj = {
a: 2,
__proto__ : {b: 2}
}
console.log('b' in obj)
console.log(Boolean(obj.b))
The second approach will check only for its own properties. Example -
var obj = {
a: 2,
__proto__ : {b: 2}
}
console.log(obj.hasOwnProperty('b'))
The difference between the first and the third is if there is a property which has value undefined the third approach is going to give false while first will give true.
var obj = {
b : undefined
}
console.log(Boolean(obj.b))
console.log('b' in obj);
Given myObject object and “myKey” as key name:
Object.keys(myObject).includes('myKey')
or
myObject.hasOwnProperty('myKey')
or
typeof myObject.myKey !== 'undefined'
The last was widely used, but (as pointed out in other answers and comments) it could also match on keys deriving from Object prototype.
Performance
Today 2020.12.17 I perform tests on MacOs HighSierra 10.13.6 on Chrome v87, Safari v13.1.2 and Firefox v83 for chosen solutions.
Results
I compare only solutions A-F because they give valid result for all cased used in snippet in details section. For all browsers
solution based on in (A) is fast or fastest
solution (E) is fastest for chrome for big objects and fastest for firefox for small arrays if key not exists
solution (F) is fastest (~ >10x than other solutions) for small arrays
solutions (D,E) are quite fast
solution based on losash has (B) is slowest
Details
I perform 4 tests cases:
when object has 10 fields and searched key exists - you can run it HERE
when object has 10 fields and searched key not exists - you can run it HERE
when object has 10000 fields and searched key exists - you can run it HERE
when object has 10000 fields and searched key exists - you can run it HERE
Below snippet presents differences between solutions
A
B
C
D
E
F
G
H
I
J
K
// SO https://stackoverflow.com/q/135448/860099
// src: https://stackoverflow.com/a/14664748/860099
function A(x) {
return 'key' in x
}
// src: https://stackoverflow.com/a/11315692/860099
function B(x) {
return _.has(x, 'key')
}
// src: https://stackoverflow.com/a/40266120/860099
function C(x) {
return Reflect.has( x, 'key')
}
// src: https://stackoverflow.com/q/135448/860099
function D(x) {
return x.hasOwnProperty('key')
}
// src: https://stackoverflow.com/a/11315692/860099
function E(x) {
return Object.prototype.hasOwnProperty.call(x, 'key')
}
// src: https://stackoverflow.com/a/136411/860099
function F(x) {
function hasOwnProperty(obj, prop) {
var proto = obj.__proto__ || obj.constructor.prototype;
return (prop in obj) &&
(!(prop in proto) || proto[prop] !== obj[prop]);
}
return hasOwnProperty(x,'key')
}
// src: https://stackoverflow.com/a/135568/860099
function G(x) {
return typeof(x.key) !== 'undefined'
}
// src: https://stackoverflow.com/a/22740939/860099
function H(x) {
return x.key !== undefined
}
// src: https://stackoverflow.com/a/38332171/860099
function I(x) {
return !!x.key
}
// src: https://stackoverflow.com/a/41184688/860099
function J(x) {
return !!x['key']
}
// src: https://stackoverflow.com/a/54196605/860099
function K(x) {
return Boolean(x.key)
}
// --------------------
// TEST
// --------------------
let x1 = {'key': 1};
let x2 = {'key': "1"};
let x3 = {'key': true};
let x4 = {'key': []};
let x5 = {'key': {}};
let x6 = {'key': ()=>{}};
let x7 = {'key': ''};
let x8 = {'key': 0};
let x9 = {'key': false};
let x10= {'key': undefined};
let x11= {'nokey': 1};
let b= x=> x ? 1:0;
console.log(' 1 2 3 4 5 6 7 8 9 10 11');
[A,B,C,D,E,F,G,H,I,J,K ].map(f=> {
console.log(
`${f.name} ${b(f(x1))} ${b(f(x2))} ${b(f(x3))} ${b(f(x4))} ${b(f(x5))} ${b(f(x6))} ${b(f(x7))} ${b(f(x8))} ${b(f(x9))} ${b(f(x10))} ${b(f(x11))} `
)})
console.log('\nLegend: Columns (cases)');
console.log('1. key = 1 ');
console.log('2. key = "1" ');
console.log('3. key = true ');
console.log('4. key = [] ');
console.log('5. key = {} ');
console.log('6. key = ()=>{} ');
console.log('7. key = "" ');
console.log('8. key = 0 ');
console.log('9. key = false ');
console.log('10. key = undefined ');
console.log('11. no-key ');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"> </script>
This shippet only presents functions used in performance tests - it not perform tests itself!
And here are example results for chrome
Now with ECMAScript22 we can use hasOwn instead of hasOwnProperty (Because this feature has pitfalls )
Object.hasOwn(obj, propKey)
Here is another option for a specific case. :)
If you want to test for a member on an object and want to know if it has been set to something other than:
''
false
null
undefined
0
...
then you can use:
var foo = {};
foo.bar = "Yes, this is a proper value!";
if (!!foo.bar) {
// member is set, do something
}
some easier and short options depending on the specific use case:
to check if the property exists, regardless of value, use the in operator ("a" in b)
to check a property value from a variable, use bracket notation (obj[v])
to check a property value as truthy, use optional
chaining (?.)
to check a property value boolean, use double-not / bang-bang / (!!)
to set a default value for null / undefined check, use nullish coalescing operator (??)
to set a default value for falsey value check, use short-circuit logical OR operator (||)
run the code snippet to see results:
let obj1 = {prop:undefined};
console.log(1,"prop" in obj1);
console.log(1,obj1?.prop);
let obj2 = undefined;
//console.log(2,"prop" in obj2); would throw because obj2 undefined
console.log(2,"prop" in (obj2 ?? {}))
console.log(2,obj2?.prop);
let obj3 = {prop:false};
console.log(3,"prop" in obj3);
console.log(3,!!obj3?.prop);
let obj4 = {prop:null};
let look = "prop"
console.log(4,"prop" in obj4);
console.log(4,obj4?.[look]);
let obj5 = {prop:true};
console.log(5,"prop" in obj5);
console.log(5,obj5?.prop === true);
let obj6 = {otherProp:true};
look = "otherProp"
console.log(6,"prop" in obj6);
console.log(6,obj6.look); //should have used bracket notation
let obj7 = {prop:""};
console.log(7,"prop" in obj7);
console.log(7,obj7?.prop || "empty");
I see very few instances where hasOwn is used properly, especially given its inheritance issues
There is a method, "hasOwnProperty", that exists on an object, but it's not recommended to call this method directly, because it might be sometimes that the object is null or some property exist on the object like: { hasOwnProperty: false }
So a better way would be:
// Good
var obj = {"bar": "here bar desc"}
console.log(Object.prototype.hasOwnProperty.call(obj, "bar"));
// Best
const has = Object.prototype.hasOwnProperty; // Cache the lookup once, in module scope.
console.log(has.call(obj, "bar"));
An ECMAScript 6 solution with reflection. Create a wrapper like:
/**
Gets an argument from array or object.
The possible outcome:
- If the key exists the value is returned.
- If no key exists the default value is returned.
- If no default value is specified an empty string is returned.
#param obj The object or array to be searched.
#param key The name of the property or key.
#param defVal Optional default version of the command-line parameter [default ""]
#return The default value in case of an error else the found parameter.
*/
function getSafeReflectArg( obj, key, defVal) {
"use strict";
var retVal = (typeof defVal === 'undefined' ? "" : defVal);
if ( Reflect.has( obj, key) ) {
return Reflect.get( obj, key);
}
return retVal;
} // getSafeReflectArg
Showing how to use this answer
const object= {key1: 'data', key2: 'data2'};
Object.keys(object).includes('key1') //returns true
We can use indexOf as well, I prefer includes
You need to use the method object.hasOwnProperty(property). It returns true if the object has the property and false if the object doesn't.
The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).
const object1 = {};
object1.property1 = 42;
console.log(object1.hasOwnProperty('property1'));
// expected output: true
console.log(object1.hasOwnProperty('toString'));
// expected output: false
console.log(object1.hasOwnProperty('hasOwnProperty'));
// expected output: false
Know more
Don't over-complicate things when you can do:
var isProperty = (objectname.keyname || "") ? true : false;
It Is simple and clear for most cases...
A Better approach for iterating on object's own properties:
If you want to iterate on object's properties without using hasOwnProperty() check,
use for(let key of Object.keys(stud)){} method:
for(let key of Object.keys(stud)){
console.log(key); // will only log object's Own properties
}
full Example and comparison with for-in with hasOwnProperty()
function Student() {
this.name = "nitin";
}
Student.prototype = {
grade: 'A'
}
let stud = new Student();
// for-in approach
for(let key in stud){
if(stud.hasOwnProperty(key)){
console.log(key); // only outputs "name"
}
}
//Object.keys() approach
for(let key of Object.keys(stud)){
console.log(key);
}

Why can ES6 Symbol properties be made enumerable by Object.defineProperty?

In ES6 properties can be defined as symbol properties:
var symbol = Symbol();
var object = {};
object[symbol] = 'value';
MDN defines enumerable properties as 'those which can be iterated by a for..in loop' (1). Symbol properties are never iterated by a for...in loop, therefore they can be considered non-enumerable (2).
Does it make any sense, then, that you can do this:
Object.defineProperty(object, symbol, {
value: 'value',
enumerable: true
});
and that querying object for it's descriptor does indeed confirm that this property is enumerable:
Object.getOwnPropertyDescriptor(object, symbol)
// -> { enumerable: true }
Why? What use is this?
(1) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
(2) for...in uses [[Enumerate]], which only includes string keys. Probably the definition on MDN should be changed now that we have symbol properties.
Yes, there's a reason for allowing Symbol properties to be enumerable: Object.assign:
let s1 = Symbol();
let s2 = Symbol();
let s3 = Symbol();
let original = {};
original[s1] = "value1"; // Enumerable
Object.defineProperty(original, s2, { // Enumerable
enumerable: true,
value: "value2"
});
Object.defineProperty(original, s3, { // Non-enumerable
value: "value3"
});
let copy = {};
Object.assign(copy, original);
console.log("copy[s1] is " + copy[s1]); // value1, because it was enumerable
console.log("copy[s2] is " + copy[s2]); // value2, because it was enumerable
console.log("copy[s3] is " + copy[s3]); // undefined, because it wasn't enumerable
Live Copy on Babel's REPL.
Just for clarity:
MDN defines enumerable properties as 'those which can be iterated by a for..in loop' (1).
That's simply wrong for ES6 (ES2015). It was a reasonable, if simplistic, definition in ES5 and earlier, no it's no longer even simplistically correct because of Symbols. I've fixed the article.
This is a CW because it was the outgrowth of the comments on the question.
This is because the rules for enumeration include a clause requiring string keys. Bear in mind that enumeration and asking for keys are different operations with entirely different rules.
Looking at the section for for ... in/for ... of head evaluation (13.7.5.12), it states that the iteration is done using:
If iterationKind is enumerate, then
c. Return obj.[[Enumerate]]().
The description of [[Enumerate]] (9.1.11) very clearly states that it:
Return an Iterator object (25.1.1.2) whose next method iterates over all the String-valued keys of enumerable properties of O.
The check for enumerable properties comes later in the body, and the pseudo-code example makes this even more clear:
function* enumerate(obj) {
let visited=new Set;
for (let key of Reflect.ownKeys(obj)) {
if (typeof key === "string") { // type check happens first
let desc = Reflect.getOwnPropertyDescriptor(obj,key);
if (desc) {
visited.add(key);
if (desc.enumerable) yield key; // enumerable check later
}
}
}
...
}
(comments mine)
Clearly, properties with non-string keys will not be enumerated. Using this example:
var symbol = Symbol();
var object = {};
Object.defineProperty(object, symbol, {
value: 'value',
enumerable: true
});
Object.defineProperty(object, 'foo', {
value: 'bar',
enumerable: true
});
Object.defineProperty(object, 'bar', {
value: 'baz',
enumerable: false
});
Object.defineProperty(object, () => {}, {
value: 'bin',
enumerable: true
});
for (let f in object) {
console.log(f, '=', object[f]);
}
for (let k of Object.getOwnPropertyNames(object)) {
console.log(k);
}
you can verify that in Babel and Traceur.
However, you'll see two interesting things:
getOwnPropertyNames includes non-enumerable properties. This makes sense, as it follows completely different rules.
for...in includes non-string properties under both transpilers. This does not seem to match the spec, but does match ES5's behavior.

if (key in object) or if(object.hasOwnProperty(key)

Do the following two statements produce the same output? Is there any reason to prefer one way to the other?
if (key in object)
if (object.hasOwnProperty(key))
Be careful - they won't produce the same result.
in will also return true if key gets found somewhere in the prototype chain, whereas Object.hasOwnProperty (like the name already tells us), will only return true if key is available on that object directly (its "owns" the property).
I'l try to explain with another example.
Say we have the following object with two properties:
function TestObj(){
this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';
Let's create instance of TestObj:
var o = new TestObj();
Let's examine the object instance:
console.log(o.hasOwnProperty('name')); // true
console.log('name' in o); // true
console.log(o.hasOwnProperty('gender')); // false
console.log('gender' in o); // true
Conclusion:
in operator returns true always, if property is accessible by the object, directly or from the prototype
hasOwnProperty() returns true only if property exists on the instance, but not on its prototype
If we want to check that some property exist on the prototype, logically, we would say:
console.log(('name' in o) && !o.hasOwnProperty('name')); //false
console.log(('gender' in o) && !o.hasOwnProperty('gender')); //true - it's in prototype
Finally:
So, regarding to statement that these two conditions ...
if (key in object)
if (object.hasOwnProperty(key))
...produce the same result, the answer is obvious, it depends.
in will also check for inherited properties, which is not the case for hasOwnProperty.
In summary, hasOwnProperty() does not look in the prototype while in does look in the prototype.
Taken from O'Reilly High Performance Javascript:
You can determine whether an object has an instance member with a
given name by using the hasOwnProperty() method and passing in the
name of the member. To determine whether an object has access to a
property with a given name, you can use the in operator. For example:
var book = {
title: "High Performance JavaScript",
publisher: "Yahoo! Press"
};
alert(book.hasOwnProperty("title")); //true
alert(book.hasOwnProperty("toString")); //false
alert("title" in book); //true
alert("toString" in book); //true
In this code, hasOwnProperty() returns true when “title” is passed in
because title is an object instance; the method returns false when
“toString” is passed in because it doesn’t exist on the instance. When
each property name is used with the in operator, the result is true
both times because it searches the instance and prototype.
You got some really great answers.
I just want to offer something that will save you the need for checking "hasOwnProperty" while iterating an object.
When creating an object usually people will create it in this way:
const someMap = {}
// equivalent to: Object.create(Object.prototype)
// someMap.constructor will yield -> function Object() { [native code] }
Now, if you want to iterate through "someMap" you will have to do it this way:
const key
for(key in someMap ){
if (someMap.hasOwnProperty(key)) {
// Do something
}
}
We are doing so in order to avoid iterating over inherited properties.
If you intend to create a simple object that will only be used as a "map" (i.e. key - value pairs) you can do so like that:
const newMap = Object.create(null);
// Now, newMap won't have prototype at all.
// newMap.constructor will yield -> undefined
So now it will be safe to iterate like this:
for(key in cleanMap){
console.log(key + " -> " + newMap [key]);
// No need to add extra checks, as the object will always be clean
}
I learned this awesome tip here
The other form (called for in) enumerates the property names (or keys)
of an object. On each iteration, another property name string from the
object is assigned to the variable. It is usually necessary to test
object.hasOwnProperty(variable) to determine whether the property name
is truly a member of the object or was found instead on the prototype chain.
for (myvar in obj) {
if (obj.hasOwnProperty(myvar)) { ... } }
(from Crockford's Javascript: The Good Parts)
As other answers indicated, hasOwnProperty will check for an object own properties in contrast to in which will also check for inherited properties.
New method 2021 - Object.hasOwn() as a replacement for Object.hasOwnProperty()
Object.hasOwn() is intended as a replacement for Object.hasOwnProperty() and is a new method available to use (yet still not fully supported by all browsers like as you can see here - https://caniuse.com/?search=hasOwn
)
Object.hasOwn() is a static method which returns true if the specified object has the specified property as its own property. If the property is inherited, or does not exist, the method returns false.
const person = { name: 'dan' };
console.log(Object.hasOwn(person, 'name'));// true
console.log(Object.hasOwn(person, 'age'));// false
const person2 = Object.create({gender: 'male'});
console.log(Object.hasOwn(person2, 'gender'));// false
It is recommended to this method use over the Object.hasOwnProperty() because it also works for objects created by using Object.create(null) and for objects that have overridden the inherited hasOwnProperty() method. Although it's possible to solve these kind of problems by calling Object.prototype.hasOwnProperty() on an external object, Object.hasOwn() overcome these problems, hence is preferred (see examples below)
let person = {
hasOwnProperty: function() {
return false;
},
age: 35
};
if (Object.hasOwn(person, 'age')) {
console.log(person.age); // true - the remplementation of hasOwnProperty() did not affect the Object
}
let person = Object.create(null);
person.age = 35;
if (Object.hasOwn(person, 'age')) {
console.log(person.age); // true - works regardless of how the object was created
}
More about Object.hasOwn can be found here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn
Browser compatibility - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility
Another way to have only ownproperties is :
<script type="text/javascript">"use strict";
const obj = Object.create({cle:"valeur"});
obj.a = "aaa";
obj.b = "bbb";
obj.c = "ccc";
for(let key=0 ; key < Object.keys(obj).length ; key++){
if(Object.keys(obj)[key]==="cle")
console.log(key , Object.keys(obj)[key] , Object.values(obj)[key]);
// none
if(Object.keys(obj)[key]==="b")
console.log(key , Object.keys(obj)[key] , Object.values(obj)[key]);
// 1 'b' 'bbb'
console.log(key , Object.keys(obj)[key] , Object.values(obj)[key]);
// 0 'a' 'aaa'
// 1 'b' 'bbb'
// 2 'c' 'ccc'
}
console.log(Object.getOwnPropertyDescriptor(obj,"cle"));
// undefined
console.log(Object.getOwnPropertyDescriptor(obj,"c"));
// {value:'ccc', writable:true, enumerable:true, configurable:true}
</script>
The first version is shorter (especially in minified code where the variables are renamed)
a in b
vs
b.hasOwnProperty(a)
Anyway, as #AndreMeinhold said, they do not always produce the same result.

What is property in hasOwnProperty in JavaScript?

Consider:
if (someVar.hasOwnProperty('someProperty') ) {
// Do something();
} else {
// Do somethingElse();
}
What is the right use/explanation of hasOwnProperty('someProperty')?
Why can't we simply use someVar.someProperty to check if an object someVar contains property with name someProperty?
What is a property in this case?
What property does this JavaScript check?
hasOwnProperty returns a boolean value indicating whether the object on which you are calling it has a property with the name of the argument. For example:
var x = {
y: 10
};
console.log(x.hasOwnProperty("y")); //true
console.log(x.hasOwnProperty("z")); //false
However, it does not look at the prototype chain of the object.
It's useful to use it when you enumerate the properties of an object with the for...in construct.
If you want to see the full details, the ES5 specification is, as always, a good place to look.
Here is a short and precise answer:
In JavaScript, every object has a bunch of built-in key-value pairs that have meta information about the object. When you loop through all the key-value pairs using for...in construct/loop for an object you're looping through this meta-information key-value pairs too (which you definitely don't want).
Using hasOwnPropery(property) filters-out these unnecessary looping through meta information and directly checks that is the parameter property is a user-given property in the object or not.
By filters-out, I mean, that hasOwnProperty(property) does not look if, property exists in Object's prototype chain aka meta information.
It returns boolean true/false based on that.
Here is an example:
var fruitObject = {"name": "Apple", "shape": "round", "taste": "sweet"};
console.log(fruitObject.hasOwnProperty("name")); //true
console.log(Object.prototype.hasOwnProperty("toString")) // true because in above snapshot you can see, that there is a function toString in meta-information
I hope it's clear!
It checks:
Returns a Boolean value indicating whether an object has a property with the specified name
The hasOwnProperty method returns true if the object has a property of the specified name, false if it does not. This method does not check if the property exists in the object's prototype chain; the property must be a member of the object itself.
Example:
var s = new String("Sample");
document.write(s.hasOwnProperty("split")); //false
document.write(String.prototype.hasOwnProperty("split")); //true
Summary:
hasOwnProperty() is a function which can be called on any object and takes a string as an input. It returns a boolean which is true if the property is located on the object, otherwise it returns false. hasOwnProperty() is located on Object.prototype and thus available for any object.
Example:
function Person(name) {
this.name = name;
}
Person.prototype.age = 25;
const willem = new Person('willem');
console.log(willem.name); // Property found on object
console.log(willem.age); // Property found on prototype
console.log(willem.hasOwnProperty('name')); // 'name' is on the object itself
console.log(willem.hasOwnProperty('age')); // 'age' is not on the object itself
In this example a new Person object is created. Each Person has its own name which gets initialized in the constructor. However, the age is not located on the object but on the prototype of the object. Therefore hasOwnProperty() does return true for name and false for age.
Practical applications:
hasOwnProperty() can be very useful when looping over an object using a for in loop. You can check with it if the properties are from the object itself and not the prototype. For example:
function Person(name, city) {
this.name = name;
this.city = city;
}
Person.prototype.age = 25;
const willem = new Person('Willem', 'Groningen');
for (let trait in willem) {
console.log(trait, willem[trait]); // This loops through all properties, including the prototype
}
console.log('\n');
for (let trait in willem) {
if (willem.hasOwnProperty(trait)) { // This loops only through 'own' properties of the object
console.log(trait, willem[trait]);
}
}
You use object.hasOwnProperty(p) to determine if an object has an enumerable property p-
An object can have its own prototype, where 'default' methods and attributes are assigned to every instance of the object. hasOwnProperty returns true only for the properties that were specifically set in the constructor, or added to the instance later.
To determine if p is defined at all, anywhere, for the object, use if(p instanceof object), where p evaluates to a property-name string.
For example, by default all objects have a 'toString' method, but it will not show up in hasOwnProperty.
hasOwnProperty is a proper way of checking an object has a property or not. someVar.someProperty cannot be used as an alternative to this situation. The following condition will show a good difference:
const someVar = { isFirst: false };
// The condition is true, because 'someVar' has property 'isFirst'
if (someVar.hasOwnProperty('isFirst')) {
// Code runs
}
// The condition is false, because 'isFirst' is false.
if (someVar.isFirst) {
// Code does not runs here
}
Hence someVar.isFirst cannot be used alternative to someVar.hasOwnProperty('isFirst').
hasOwnProperty is a normal JavaScript function that takes a string argument.
In your case, somevar.hasOwnProperty('someProperty'), it checks the somevar function has somepropery or not - it returns true and false.
Say
function somevar() {
this.someProperty = "Generic";
}
function welcomeMessage()
{
var somevar1 = new somevar();
if(somevar1.hasOwnProperty("name"))
{
alert(somevar1.hasOwnProperty("name")); // It will return true
}
}
2021 - Object.hasOwn as a replacement for Object.hasOwnProperty()
As other answers indicated, hasOwnProperty will check for an object own properties in contrast to in which will also check for inherited properties.
There is a new alternative method called Object.hasOwn() and is intended to be a replacement for Object.hasOwnProperty()**
Object.hasOwn() is a static method which returns true if the specified object has the specified property as its own property. If the property is inherited, or does not exist, the method returns false.
const person = { name: 'dan' };
console.log(Object.hasOwn(person, 'name'));// true
console.log(Object.hasOwn(person, 'age'));// false
const person2 = Object.create({gender: 'male'});
console.log(Object.hasOwn(person2, 'gender'));// false
It is recommended to this method use over the Object.hasOwnProperty() because it also works for objects created by using Object.create(null) and for objects that have overridden the inherited hasOwnProperty() method. Although it's possible to solve these kind of problems by calling Object.prototype.hasOwnProperty() on an external object, Object.hasOwn() overcome these problems, hence is preferred (see examples below)
let person = {
hasOwnProperty: function() {
return false;
},
age: 35
};
if (Object.hasOwn(person, 'age')) {
console.log(person.age); // true - the remplementation of hasOwnProperty() did not affect the Object
}
let person = Object.create(null);
person.age = 35;
if (Object.hasOwn(person, 'age')) {
console.log(person.age); // true - works regardless of how the object was created
}
More about Object.hasOwn can be found here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn
Browser compatibility - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility
What is the right use/explanation of hasOwnProperty('someProperty') ?
The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).
const someVar = {};
someVar.someProperty = 'Foo';
console.log(someVar.hasOwnProperty('someProperty'));
// expected output: true
console.log(someVar.hasOwnProperty('someProperty1'));
// expected output: false
Why can't we simply use someVar.someProperty to check if an object someVar contains property with name someProperty ?
someVar.someProperty will return the property value, You can not check that this property is available in the object or not via someVar.someProperty.
Now in ES2022, A new method has been introduced which is Object.hasOwn(<object reference>, <property name>) this method is intended as a replacement for Object.hasOwnProperty() which overcome some limitations of .hasOwnProperty().
Scene A:
const objA = { a: 1, b: 2 }
for (const key in objA) {
if (objA.hasOwnProperty(key)) {
console.log(objA[key])
}
}
Output
1
2
Scene B:
const objB = {
a: 1,
b: 2,
hasOwnProperty() {
return false
}
}
for (const key in objB) {
if (objB.hasOwnProperty(key)) {
console.log(objB[key])
}
}
Outputs nothing
Because JavaScript doesn't protect the property of hasOwnProperty.
So you can use it like this:
for (const key in objB) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
console.log(objB[key])
}
}
It checks if an object has a property. It works the same as if(obj.prop), as far as I know.

Copying attributes in Javascript

Javascript - The Definitive Guide (6ed) shows the following code:
Originally we have this function
/*
* Copy the enumerable properties of p to o, and return o.
* If o and p have a property by the same name, o's property is overwritten.
* This function does not handle getters and setters or copy attributes.
*/
function extend(o, p) {
for(prop in p) { // For all props in p.
o[prop] = p[prop]; // Add the property to o.
}
return o;
}
Then the author decided to rewrite it and extend the copy ability (able to copy accessor properties, for example):
/*
* Add a nonenumerable extend() method to Object.prototype.
* This method extends the object on which it is called by copying properties
* from the object passed as its argument. All property attributes are
* copied, not just the property value. All own properties (even non-
* enumerable ones) of the argument object are copied unless a property
* with the same name already exists in the target object.
*/
Object.defineProperty(Object.prototype,
"extend", // Define Object.prototype.extend
{
writable: true,
enumerable: false, // Make it nonenumerable
configurable: true,
value: function(o) { // Its value is this function
// Get all own props, even nonenumerable ones
var names = Object.getOwnPropertyNames(o);
// Loop through them
for(var i = 0; i < names.length; i++) {
// Skip props already in this object
if (names[i] in this) continue;
// Get property description from o
var desc = Object.getOwnPropertyDescriptor(o,names[i]);
// Use it to create property on this
Object.defineProperty(this, names[i], desc);
}
}
});
I don't understand why we are extending Object.prototype, and now how do we use this to copy all the attributes in Object y to Object x? How do I use Object.prototype.extend ?
I decided to test if I can do something quicker. I don't understand why the following custom code doesn't work.
function extend(o){
var p = new Object();
for( prop in o)
Object.defineProperty(p,prop,Object.getOwnPropertyDescriptor(o,prop));
return p;
}
// Let's perform a simple test
var o = {};
Object.defineProperty(o, "x", { value : 1,
writable: true,
enumerable: false,
configurable: true});
o.x; // => 1
Object.keys(o) // => []
var k = new Object(extend(o)); // Good, k.x => 1
// More test
Object.defineProperty(o, "x", { writable: false });
Object.defineProperty(o, "x", { value: 2 });
Object.defineProperty(o, "x", { get: function() { return 0; } });
o.x // => 0
// Perform the creation again
var k = new Object(extend(o)); // bad. k.x is 1, not 0
// so the getter property didn't copy to k !!!
Sorry I am pretty new to Javascript. Thanks for the help in advance. All these questions are related to the transformation / rewrite of the function "extend"
I edited the my test code. Sorry!
The purpose of defining this in the prototype is so that every Object can call it as a member function, like this:
yourobject.extend(anotherObject);
Most coders find that more elegant than having to pass both objects as parameters, like this:
extend(yourObject, anotherObject);
Modifying prototypes is a great way to add useful "methods" to objects.
side note: I would not recommend using the author's extend code. It doesn't properly check hasOwnProperty.
You seem to misunderstand the use of prototype. Prototyping is JavaScript's way of dealing with inheritance. The extend function is terminology loaned from languages like C++ and Java and is not native to JavaScript.
Here's a guide on prototype: http://mckoss.com/jscript/object.htm
I have several years experience writing JavaScript and I'd recommend not using prototyping at all. JavaScript has other ways of dealing with data modeling that I find more elegant. It's still useful to understand how prototyping works though because it deepens your understanding of Objects.

Categories