javascript object prototype property access - javascript

Here is a jsFiddle of my question: http://jsfiddle.net/4wyvv/1/
Basically:
//constructor function
function Maker(){
var str;
this.init = function(str){
this.str = str;
};
this.msg = function(){
return this.str;
};
}
//object from Maker
var obj = new Maker();
obj.init("Hi my name is Dan");
//make sure everything exists and has worked as expected
Audit.Log(obj.msg());
//look in Maker.prototype for the constructor property
Audit.Log(obj.constructor);
//look in Maker.prototype for the constructor property
Audit.Log(Maker.prototype.constructor);
//now look for all makers prototype properties, this should list atleast "constructor"
for(var i in Maker.prototype){
Audit.Log(i);
}
Why does the foreach loop not put out anything? It should at least put out constructor as I showed that Maker.prototype.constructor exists.

Some properties of object like "constructor" are hidden or to be more precise non-enumerable so they are not enumerated using a for in loop like this, In ECMA5 we have a method that can get all the properties
Object.getOwnPropertyNames(Maker.prototype)
this is give you
["constructor"]
Here is a detailed explanation : How to display all methods of an object in Javascript?

From MDN
for..in Iterates over the enumerable properties of an object, in
arbitrary order. For each distinct property, statements can be
executed.
Things like constructor, toString, hasOwnProperty are non enumerable properties and they won't be listed in for..in

Related

Access to internal object fields in Js

Having this code
var a = {date : 12};
for(var t in a){
alert(t);
}
I have one alert with date property.
But everywhere (i.e. here) i see that it is needed to write :
for (var property in object) {
if (object.hasOwnProperty(property)) {
// do stuff
}
}
So why i don't see internal properties of object?
The for..in syntax iterates every property of the object, including those found on the prototype chain (if they are enumerable). This is usually not what you want, so the hasOwnProperty check is usually recommended.
In your case it's not necessary, as your plain object doesn't inherit any enumerable properties from the Object prototype (the only thing in its prototype chain)
Also, for..in gives you the property names (keys) of the object, if you're interested in the value of that particular property, you have to use the bracket notation, extending your example to this:
var a = {date : 12};
for(var t in a){
alert(a[t]);
}
In JavaScript there exists the 'prototype chain', a form of inheritance. If you were to add a property to the prototype of a, and then add your date property directly onto a, your for loop would find both those properties.
The hasOwnProperty checks whether the current property has been attached directly to the context object or whether it has been inherited through the prototype chain.
So in my example, if you had added a property to a's prototype, the hasOwnProperty condition would return false and you wouldn't "do stuff" with it.
I guess the best way to see it is through an example:
Object.prototype.aBaseProperty = 123;
var childObject = { date: 12 };
for (var property in childObject) {
console.log(property)
}
// output: date aBaseProperty
for (var property in childObject) {
if (childObject.hasOwnProperty(property)) {
console.log(property)
}
}
// output: date
Also, rather than doing the hasOwnProperty check, you might prefer
Object.keys(object).forEach(function(value, key) { ... });
Where Object.keys will only return own properties.

Javascript prototype extension weird behaviour

Can you explain me this?
JAVASCRIPT
if (typeof Array.prototype.contains != 'function') {
Array.prototype.contains = function (str){
return this.indexOf(str) > -1;
};
}
var text = "Hello world";
var tokens = text.split(" ");
console.log(tokens.length);
for (var i in tokens){
console.log(tokens[i]);
}
OUTPUT
2
"Hello"
"world"
function ()
In other words, the "contains" function i added to the Array prototype appears in the for loop as last element (but the array length is 2). Why?
Why?
Because for-in doesn't loop through array entries, it loops through enumerable properties of an object. You've created a new enumerable property on Array.prototype, and so that property shows up in for-in loops on any array.
The solutions are:
Don't do that, instead loop through arrays in any of several ways that don't have that problem, or
Use hasOwnProperty to filter out inherited properties (see link above for more), or
Define contains as a non-enumerable property via Object.defineProperty or similar (you can only do this on ES5+ engines, it cannot be shimmed).

Why "for-in" loop doesn't iterate through the prototype properties?

Let's create a new object:
var dict = {};
Known fact is that after creating a new object, this new object inherits the Object.prototype . So when I try to check if the prototype's properties were inherited I do "toString" in obj for which I get true. But when I want to put all the properties of the newly created object into an array I would see that the array is empty after finishing filling up. Have a look on the code below:
var names = [];
for (var name in dict) {
names.push(name);
};
names.length;
Fail to see why it happens.
As many said in the comments, the For-In loop enumerates only the enumerable properties in the prototype chain, and the inherited toString property is not enumerable.
If you want to iterate through the non-enumerable properties of the object prototype to see if "ToString" is there then you should get the object prototype and get its enumerable and non-enumerable properties using the getOwnPropertyNames method:
var dict = {};
var objPrototype = Object.getPrototypeOf(dict);
var propertyNames = Object.getOwnPropertyNames(objPrototype);
propertyNames.length;

Is JavaScript Object nothing but an associative array?

Ok am just going through basics of JavaScript and I was learning objects where I came across this example...
JavaScript
var person = {
firstname : "Smith",
lastname : "Bach"
};
And what we write in PHP is
$person = array(
"firstname"=>"Smith",
"lastname"=>"Bach"
);
So is this the same thing or am making a mistake in understanding the concept?
No, objects are more than that.
Object is indeed a map/dictionary, but additionally every object inherits some of the properties (key-value pairs) from another object. That other object is called prototype.
For example:
var o = {
x: 1
};
console.log(o.x === undefined); // false, obviously
console.log(o.toString === undefined); // false, inherited from prototype
Most commonly a prototype is set by creating an object with a constructor function:
var d = new Date();
console.log(d.hasOwnProperty('getYear')); // false, it's inherited
EDIT:
Here's how the prototype works using constructor functions (it's one of the ways to do OOP in JS):
// constructor function
// starts with capital letter, should be called with new
var Person = function (name, age) {
// set properties of an instance
this.name = name;
this.age = age;
};
// functions to be inherited are in the prototype
Person.prototype.sayHello = function () {
return this.name + ' is ' + this.age + ' old';
};
// new:
// - creates the object
// - sets up inheritance from prototype
// - sets the object as the context of the constructor function call (this)
var p = new Person('Jason', 27);
console.log(p.sayHello());
They are associative arrays, but not just associative arrays. There are functions available from the Object prototype (like .toString()) whose names can collide with property names. Objects can be constructed via other functions and given more inherited properties too. (Note that one thing that plain objects don't have is a .length property to count entries, like array objects have. The term "associative array" is probably not the best one to use for JavaScript objects; they're objects and that should be enough once you're familiar with JavaScript.)
edit — what I mean is this:
var o = {};
alert("toString" in o); // alerts "true"
Thus a newly-created empty object appears to have a property called "toString". The issue with JavaScript is that there's only one property accessor operator (well two, but they're two flavors of the same thing), so there's no way to distinguish between accesses to the array's contents and access to the array's API. (Also, in JavaScript it's really not a good idea to think of them using the word "array", as that means something different in JavaScript — arrays are a type of Object with special properties.)
EcmaScript 5 has mechanisms for defining object properties in such a way as to make them immutable and non-iterable, which helps some. It's still problematic if you want to store a property called "toString" in an object.

javascript looping and deleting object properties

I have an object with various properties. The name of the object is a global variable but the properties are changed at runtime by methods. Some methods add properties to the object. I'd like to add a method that loops through this object and removes all of its properties that are either null or empty. I could check each property by specifying its name and checking its state but if I add properties later, I'd have to update this cleanup method too. How can I loop through the properties of an object without know the name of the properties first.
Thanks for your suggestions.
Iteration over an object is simple - the for in loop:
for (var key in object) {
if (object.hasOwnProperty(key)) {
//Now, object[key] is the current value
if (object[key] === null || isEmpty(object[key]))
delete object[key];
}
}
isEmpty doesn't exist, you have to define it or replace it with something more meaningful, I couldn't understand what you meant by empty in your question.
I use object.hasOwnProperty because objects inherit things from Object.prototype and possibly other places (arrays for example inherit from Array.prototype, which inherits from Object.prototype). So:
object.toString; //function toString() { [native code] }
But, object.toString actually refers to Object.prototype.toString - it isn't really in your object, but when you type object.toString, the interpreter sees that there's no object.toString, so it checks up the prototype chain until it finds it.
hasOwnProperty checks if a key actually exists on an object:
object.hasOwnProperty("toString"); //false
object.foo = "bar";
object.hasOwnProperty("foo"); //true
Subscript access to objects is also simple:
var object = {foo: "bar"};
object.foo; //"bar"
object["foo"]; //"bar"
var key = "foo";
object[key]; //"bar"
Note that whatever is passed to the brackets gets converted to a string. So, for example, you can do this:
object[Object.prototype.toString] = "magic";
Object.keys(object); //["function toString() { [native code] }"]
In case you're wondering, Object.keys is an ES5 (EcmaScript 5) feature.
You can use a for each loop to iterate through the object properties.
for ( var i in obj ) {
if ( obj[i] === null ) {
delete obj[i];
}
}

Categories

Resources