I have a problem I can't solved because I can't explain this behaviour :
var A = function(value) {
this.prop = value;
};
A.prototype = {
prop: 0
};
var a = new A(1);
var b = new A(2);
console.log(a.prop);
console.log(b.prop);
output :
1
2
But, with this code (almost the same) :
var A = function(value) {
this.prop.value = value;
};
A.prototype = {
prop: {
value: 0
}
};
var a = new A(1);
var b = new A(2);
console.log(a.prop.value);
console.log(b.prop.value);
I have this output :
2
2
Can anybody explain me this ?
Thanks...
EDIT :
Here's a solution :
var A = function(value) {
this.prop = {};
this.prop.value = value;
};
A.prototype = {
};
var a = new A(1);
var b = new A(2);
console.log(a.prop.value);
console.log(b.prop.value);
In example 1, this.prop is a primitive type, which is referenced by value and thus not shared between instances.
In example 2, this.prop is an Object whose reference is initialized from the prototype from a single object, so this single object is shared by all instances.
In the last "example" solution, you create a new object with = {}, so all instances now have their own object.
More details about primitive types : Primitive value vs Reference value
prototype is created only once and it's only a simple object whose childs are attached for all instances of a function it belongs to.
So it's basically the same as if you write:
var obj = { value: 0 };
var a = {}, b = {};
a.obj = obj;
b.obj = obj;
obj.value = 2;
as you can see both a.obj and b.obj references to the same obj and both a.obj.value and b.obj.value will be 2 in this example
This is happening because in JS, objects are passed by reference, while primitives are not.
Since the prototype is shared between the 2 instances, modifying a object on it will update all instances.
Think of a prototype property as a property shared amongst all instances.
Yet you can override it on each instance, that 's what you do in the first example.
Once overriden in each instance, you do not access any more to the prototype property with obj.prop, which now refers to the instance property. You would need to use obj.prototype.prop to read it again, but this syntax is illegal : you can use obj.__proto__.prop (non standard) or Object.getPrototypeOf(obj).prop (EcmaScript 5) to do so.
In the second instance, you do not change the property in the constructor : rather you change a property of this property. So both constructor access to the very same object, then change one of its property value, so the last to set it will 'win'. Here the prototype property is not overriden ('hidden') by the instance property and accessing obj.prop in fact access 'obj.prototype.prop'.
Related
Here I have a simple code to understand how Object.create() works. Here I have a common object to be used as prototype which is prototypeObj.newObj is an object which has its prototype set to prototypeObj. Here I have another object called session which has a property called anotherObj, and anotherObj has the same prototype as newObj. But adding new value to a property called foo which resides in the prototype of anotherObj , affect newObj too. Why am I experiencing this behaviour?
Code:
var prototypeObj = {
foo: [],
addItemToFoo: function(add) {
this.foo.push(add);
}
}
function create(fooVal) {
var myProto = Object.create(prototypeObj);
myProto.foo = fooVal;
return myProto;
}
var newObj = create([1, 2]); // initialized with [1,2]
session = {
anotherObj: create(newObj.foo) // initialized with [1,2]
}
session.anotherObj.addItemToFoo(6); // pushed 6 to session.anotherObj.foo
console.log("newObj.foo is " + newObj.foo); // newObj also get 6 pushed to its foo property
console.log("anotherObj.foo is " + session.anotherObj.foo);
foo is an array, it works by reference.
anotherObj: create(newObj.foo)
You are copying the reference here, so both your old and new object will have the same array reference to insert elements in. If you want to have to different array references, you should first copy it like this create(newObj.foo.slice())
https://jsfiddle.net/x8ftnh82/
Sorry for noob question. I'm just learning JavaScript.
I have an easy Object.
var bike = {
wheels: 2,
};
I create a new one that inherits all the bike values via create() and add some new properties to new Object.
var raleigh = Object.create(bike);
raleigh.color = 'red';
When I do console.log on new raleigh Object I can't see propeties inherited from bike Object.
console.log(raleigh);
The log is:
{ color: 'red' }
How to log to console all properties including these inherited?
When an object is printed through console.log, it is printed with all its own properties and a link to the object it inherits from. You can see all the inherited properties in console, you just need to follow the prototype chain of the displayed object (typically using __proto__ or [[prototype]] keys).
When you use Object.create then your prototype will be the same the object that you are inheriting, so, to show "father" properties you could see the prototype:
console.log(raleigh);
console.log(Object.getPrototypeOf(raleigh));
Maybe you will expect something more but I think that is the fast way to show that properties.
Would this help?
I'm throwing an alert, u can check the console as well!
var bike = {
wheels: 2,
};
var raleigh = Object.create(bike);
raleigh.color = 'red';
function getAllProperties( obj ) {
var properties = [];
do {
properties= properties.concat(Object.getOwnPropertyNames( obj ));
} while ( obj = Object.getPrototypeOf( obj ) );
return properties;
}
alert(getAllProperties(raleigh));
console.log(getAllProperties(raleigh));
You could create a new Object especially for your log which has everything as own properties
function flatten_inheritance(e) {
var o = Object.create(null), i, prop;
do {
prop = Object.getOwnPropertyNames(e);
for (i = 0; i < prop.length; ++i)
if (!(prop[i] in o))
o[prop[i]] = e[prop[i]];
} while (e = Object.getPrototypeOf(e));
return o;
}
flatten_inheritance(raleigh); // Object {color: "red", wheels: 2, valueOf, toString, etc..}
If you want to stop at Object.prototype or some other prototype you can do this in the while condition for example;
while (e = Object.getPrototypeOf(e) && e !== Object.prototype);
I would recommend you only do this when debugging rather than moving all your code away from inheritance though
var User = Parse.User.extend({
// instance members
}, {
// types
TYPE_TRAINER : 1,
TYPE_ATHLETE : 2,
types: {
TYPE_TRAINER : 'Trainer',
TYPE_ATHLETE : 'Athlete'
}
});
I want to have TYPE_TRAINER and TYPE_ATHLETE maintain the values of 1 and 2 as defined prior to the types object so that I can use the types object in a template.
If you don't know about Parse, Parse.User is an extension of Backbone.Model.
Thanks!
What you're asking is not directly possible in JavaScript object literals. Object literals are always a literal value on the left hand / key side.
The closest you could get is to use the TYPE_TRAINER and TYPE_ATHLETE keys as variables to assign values via the square bracket syntax for accessing object key/value pairs:
var a = 1;
var b = 2;
var obj = {};
obj[a] = "a";
obj[b] = "b";
This will result in the obj object looking like this:
{
1: "a",
2: "b"
}
So you could do something like this, to get what you want in your code:
var userMethods = {
// types
TYPE_TRAINER : 1,
TYPE_ATHLETE : 2
};
userMethods[userMethods.TYPE_TRAINER] = 'Trainer';
userMethods[userMethods.TYPE_ATHLETE] = 'Athlete';
var User = Parse.User.extend({
// instance members
}, userMethods);
It's more code than you probably want, but it's the only way to achieve what you want because of the object literal syntax.
The Parse.Object Javascript documentation says:
You should call either:
var MyClass = Parse.Object.extend("MyClass", {
// Instance properties
}, {
// Class properties
});
or, for Backbone compatibility:
var MyClass = Parse.Object.extend({
className: "MyClass",
// Other instance properties
}, {
// Class properties
});
If you are wanting to extend the Parse.User "class" (it's an object, not a class), you need to include the className as described above because Parse.User is itself an extension of Parse.Object.
I understand that there are two ways of creating classes in JavaScript
var MyObj = function(val)
{
this.vari = val;
}
Where val will be a non static member.
Whereas,
var MyObj = new Object();
MyObj.vari = "";
This is a single object so members of it here will act like static members. My question is that how do we have both static as well as non static content in same class?
There are no classes in JavaScript, only objects.
When you create a new object you are "extending" from the function's prototype, not the function itself. In order to make a variable or function appear to be static you would have to attach it to the function used to create the object, and not its prototype.
js> var Foo = function(){ this.member = "member"; };
js> Foo.staticMember = "staticMember";
js> var f = new Foo();
js> Foo.member;
undefined
js> Foo.staticMember;
"staticMember"
js> f.member;
"member"
js> f.staticMember;
undefined
Using your first example:
var MyObj = function(val) {
this.vari = val;
};
MyObj.var2=value;
Will create a new "static" property callable as:
var o = MyObj.var2;
The first one initializes the MyObj variable with the anonymous function - it does not create the class. The MyObj may be later used as the object constructor that initializes one object field - vari. There is nothing "statis" in OOP meaning.
The second one creates the object of the Object type and initializes its property. Again, there is nothing static.
In OOP "statis" means the member of the class, e.g. variables and objects that belong to class definition. For example, the following schema demonstrates this concept:
function MyClass() {
this.objectProperty = "I'm object property";
// the following demonstrates initialization of
// the object property from class (static) property:
this.varFromStatic = MyClass.classProperty;
}
MyClass.classProperty = "I'm class (static) property";
var obj = new MyClass();
// now obj.varFromStatic contains "I'm class (static) property"
What does the Object function in JavaScript do?
For example, what happens when we do Object(1)?
It forces something to be an object. I've not seen it being used in this way though.
var num = 1;
var obj = Object(num);
alert(typeof num); //displays "number"
alert(typeof obj): //displays "object"
alert(num + "," + obj); //displays "1,1"
The preferred, faster way to create an empty object on which you can put properties and methods on is by using {}. Three possible ways to create an object:
var emptyObj = {};
var emptyObj = new Object();
var emptyObj = new Object; // Object does not need an argument, so this is valid.
From the Mozilla developer site:
The Object constructor creates an object wrapper for the given value. If the value is null or undefined, it will create and return an empty object, otherwise, it will return an object of type that corresponds to the given value.
When called in a non-constructor context, Object behaves identically.
So Object(1) produces an object that behaves similarly to the primitive value 1, but with support for object features like assigning values to properties (Object(1).foo = 2 will work, (1).foo = 2 will not).
var obj = Object("test");
Creates a String "text", it's pretty similar to
var obj2 = "test";
Notice that the type of obj2 is "String" and of obj1 "Object"
Try this:
<script>
var obj = Object("test");
console.log(obj);
console.log(typeof(obj));
console.log(obj["0"]);
obj2 = "test";
console.log(obj2);
console.log(typeof(obj2));
console.log(obj2["0"]);
</script>
Creates an object http://www.w3schools.com/js/js_objects.asp
Object function is a constructor function, all other types(like Array, String, Number) inheritate it.