Why do inherited properties print later than other properties? - javascript

let animal = {
eats: true
};
let rabbit = {
__proto__: animal, // (*)
jumps: true, // (**)
};
console.log(Object.keys(rabbit)); // [jumps]
for(let prop in rabbit) console.log(prop); // jumps, eats
Why do inherited properties in the (*) line print later than property in the (**) line when we print properties in the for..in loop, even though the (*) line is above the (**) line?

From the for...in article on MDN:
The loop will iterate over all enumerable properties of the object itself and those the object inherits from its prototype chain (properties of nearer prototypes take precedence over those of prototypes further away from the object in its prototype chain).
The traversal order, as of modern ECMAScript specification, is well-defined and consistent across implementations. Within each component of the prototype chain, all non-negative integer keys (those that can be array indices) will be traversed first in ascending order by value, then other string keys in ascending chronological order of property creation.
So, if you had included other properties on the prototype animal, and on rabbit, then those would be grouped by prototype, then ordered accordingly:
let animal = {
isAnimal: true,
eats: true,
};
let rabbit = {
__proto__: animal,
jumps: true,
isRabbit: true,
};
console.log(Object.keys(rabbit)); // ["jumps", "isRabbit"]
for (let prop in rabbit) console.log(prop);
// jumps (from rabbit)
// isRabbit (from rabbit)
// isAnimal (from animal)
// eats (from animal)

The for...in loop will capture inherited keys, whereas Object.keys will only access own properties.
The Object.* methods can only access direct properties of the object. If you want to avoid printing inherited properties, you will need an Object.prototype.hasOwnProperty check.
const animal = { eats: true };
const rabbit = {
__proto__: animal, // (*)
jumps: true, // (**)
};
console.log(Object.keys(rabbit)); // [jumps]
for (let prop in rabbit) {
if (rabbit.hasOwnProperty(prop)) {
console.log(prop); // jumps, but not eats
}
}
for (let [prop] of Object.entries(rabbit)) {
console.log(prop); // jumps
}

Object.keys(obj) simply return an array of the object's own properties, whereas for...in additionally returns the keys found in the prototype chain.
Check the reference from MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

Related

Accessing API class names in global context

I am writing some ES/JS tooling. In DevTools I can see lots of classes, e.g. ArrayBuffer. Yet when I try to extract such names from window global context, I can't see them. This snippet gives similar results in Chrome, FireFox and Opera.
MWE on JSFiddle
console.log('typeof window.ArrayBuffer:',
typeof window.ArrayBuffer);
console.log("window.hasOwnProperty('ArrayBuffer'):",
window.hasOwnProperty('ArrayBuffer'));
let c = 0;
for (let n in window) {
// console.log(n);
if (n == 'ArrayBuffer') {
console.log('FOUND: ArrayBuffer');
}
c++;
}
console.log(c + ' attributes checked')
If I uncomment the // console.log(n); line, I can see the names of the attributes, but none of the classes.
How do I access those class (API) names?
It's matter of Object's Enumerable properties.
for in (as well as Object.keys/values/entries) does not account for non enumerable properties:
window.hasOwnProperty('ArrayBuffer'); // true
window.propertyIsEnumerable('ArrayBuffer'); // false
// Therefore will not show up in for-in loop
To create a non-enumerable object property, an example is by using Object.defineProperty
const obj = {a: 1, b: 2, c: 3};
for (const prop in obj) console.log(obj[prop]); // 1 2 3
Object.defineProperty(obj, "d", {
value: 4,
// enumerable: false, // defaults to false!!
// set to true to make it enumerable
});
for (const prop in obj) console.log(obj[prop]); // 1 2 3 (no 4 visible)
// Same goes for iterating using Object.keys and Object.values:
console.log(...Object.values(obj)) // 1 2 3 (no 4 visible)
To get all the properties of an Object you might use instead Object.getOwnPropertyNames:
const props = Object.getOwnPropertyNames(window);
console.log(props.includes('ArrayBuffer')); // true
console.log(props.some(pr => pr === 'ArrayBuffer')); // true
console.log(props.findIndex(pr => pr === 'ArrayBuffer') > -1); // true
console.log(props.length); // 963
console.log(Reflect.ownKeys(window).length); // 963
// See them all:
console.log(props);
// Loop them all:
// props.forEach(pr => console.log(pr));
Keep in mind that for...in loops only enumerable properties - with the exception of Symbols.
To get an Array ot the Object's own-property keys with Symbols use Reflect.ownKeys
The Reflect.ownKeys method returns an array of the target object's own property keys. Its return value is equivalent to Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
Additional read:
Enumerability and ownership of properties
What are the benefits of non-enumerable Object properties
Use Object.getOwnPropertyNames() to get all properties (including non-enumerable properties except for those which use Symbol). Then loop through them to find the class name:
Object.getOwnPropertyNames(window).forEach((n) => {
if (n === 'ArrayBuffer') {
console.log('FOUND: ArrayBuffer');
}
})

The difference between customize function and native function in prototype

'For In' can traverse Array (value/properties/function).
let arr = [1,2,3,4];
arr.__proto__.con = function(){console.log('from array');}
for(let item in arr){
console.log(item);
}
The result will be:
1,2,3,4,con
why does native function like 'toString'/'split' not be printed?
what is the difference?
In my mind, they(con and toString) all belong to the prototype of Array.
The for...in statement...
iterates over all non-Symbol, enumerable properties of an object. (source: MDN)
However, if you look at the ECMA specification, in the item "Properties of the Array Prototype Object", you'll see that:
The Array prototype object is the intrinsic object %ArrayPrototype%. The Array prototype object is an Array exotic objects and has the internal methods specified for such objects. It has a length property whose initial value is 0 and whose attributes are { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }.
That applies to concat, filter, map, forEach, sort, toString etc...
You can use Object.getOwnPropertyDescriptor to check those attributes. For instance:
console.log(Object.getOwnPropertyDescriptor(Array.prototype, "concat"));
Finally, for setting those methods with {enumerable: false}, have a look at the other answer.
It doesn't matter that the method is assigned to the prototype. Properties of any type of object are enumerable by default, whether they are assigned to the object's prototype or directly to the object:
class MyClass {
constructor() {
this.x = 10;
}
}
let test = new MyClass();
test.y = 20;
for(let item in test) {console.log(item) } // logs x, y
Native methods like toString are set to be non-enumerable, for the obvious reason that you don't often want to loop through them. User methods or properties can also be set to be non-enumerable, by using Object.defineProperty:
Object.defineProperty(test, "z", {value: 42, enumerable: false})
console.log(test.z); // 42
for(let item in test) {console.log(item)} // still only x, y

Does the spread operator not copy over the prototype?

The following code does not appear to copy over an object's prototype.
const animalProto = {
eat() {
// function body
},
sleep() {
// function body
},
}
function animalCreator(proto, attributes) {
return {...Object.create(proto), ...attributes}
}
const cat = animalCreator(animalProto, { name: 'garfield' })
cat.eat() // this is an error; function is not defined; it doesn't appear to link the prototype chain.
If I replace the spread with the following it works:
return Object.assign(Object.create(proto), attributes)
Essentially my question is why does Object.assign work but not the spread operator. Is there something Object.assign is doing that the spread operator is missing?
See the docs:
It copies own enumerable properties from a provided object onto a new object.
"Own enumerable" means that properties on the prototype will not be included.
If you spread an object with inherited properties (such as an object immediately created with Object.create), none of those inherited properties will be present in the result.
Object.assign is slightly different - it assigns all properties to the right of the first to the first. It would be more similar to spread if you had passed an empty object as the first argument:
return Object.assign({}, Object.create(proto), attributes)
in which case nothing in proto would be reflected in the output.
const proto = { foo: 'bar' };
const result = Object.assign({}, Object.create(proto), { another: 'prop' });
console.log(result);
Object.create() makes a new object that is prototype linked to the object passed to it. This means that the returned object doesn't get a copy of the parent's attributes, it just has a link to the parent prototype. The object spread only copies the objects own enumerable properties, which doesn't include those up the prototype chain.
const animalProto = {
eat() {
// function body
},
sleep() {
// function body
},
}
let o = Object.create(animalProto)
// o doesn't have it's own eat or sleep.
console.log(Object.getOwnPropertyNames(o))
console.log({...o}) // empty

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.

Categories