Why this javascript code not working? - javascript

This code work :
function class1(){
this.x5 = 5;
this.x6 = 6;
this.prototype = 5;
}
function class2(){
this.x3 = 3;
this.x4 = 4;
}
class2.prototype = new class1();
var obj1 = new class2();
alert(obj1.x5 ); // alert me 5
But why this not working :
function class1(){
this.x5 = 5;
this.x6 = 6;
this.prototype = 5;
}
function class2(){
this.x3 = 3;
this.x4 = 4;
this.prototype = new class1(); // or class2.prototype = new class1();
}
var obj1 = new class2();
alert(obj1.x5); // alert me "undefinded"

You can't set the prototype inside of the function like that. When invoking a function with the new operator, then a new object is created, and this gets set to that object. Objects don't have a publicly accessible prototype property that you can set. Their prototype property is actually __proto__, which is not accessible (although some browsers do let you get at it).
In your second example, you're just setting a plain ol' vanilla property named "prototype" with a value.
the prototype property on a function is also not the prototype! Confusing, eh? What it really is is something of a "prototype template". It basically means "when you create an object using this function as the constructor, set their prototype to whatever I have set in the prototype property." This can be very confusing until you grok it.
Also Note
Your first example doesn't work either (try it here), you are setting the prototype property of the function after the instance was already created. So that instance was already given a different prototype object. If you created a second instance of class2, it would alert the property correctly.

Related

changing value in prototype does not work in JavaScript

I am new in JS, lets have a look on my code bellow.
I want to change value of legs property of mouse to 2 while using proto but I am unable to change it. All I am getting in output is 4. Please help why is this ?
function Animal() {
this.legs = 4;
}
var mouse = new Animal();
mouse.__proto__.legs = 2;
console.log(mouse.legs);
You can't change instance property this way.
mouse.__proto__ contains constructor function Animal.
If you want to change only mouse's legs you have to do it this way:
mouse.legs = 2
If you want to change every future animals - you unfortunately can't. new Animal() will always reference to original constructor function.
When you call new Animal, the JS engine doesn't reference Animal.prototype.constructor, it uses the Animal as the constructor function and Animal.prototype as the newly created object's prototype, ignoring Animal.prototype.constructor.
As commented, the leg you are trying to access is a self owned property and not on prototype.
Following is a sample:
function Animal() {
this.legs = 4;
}
Animal.prototype.legs = 8;
var mouse = new Animal();
mouse.legs = 2;
console.log(mouse.legs, mouse.__proto__.legs);
That said, if you wish to have a override concept implementation, always remember, never mutate/change property on prototype.
Idea is to have common property on prototype and have custom property on self.
Following is a sample depicting the same:
function Animal() { this.legs = 4; }
function Reptile() { this.legs = 4; }
Reptile.prototype = new Animal();
var mouse = new Reptile();
console.log('Mouse details : ', mouse.legs, mouse.__proto__.legs);
var snake = new Reptile();
snake.leg = 0;
console.log('Snake details : ', snake.legs, snake.__proto__.legs);
snake.__proto__.legs = 0;
console.log('After mutation')
console.log('Mouse details : ', mouse.legs, mouse.__proto__.legs);
console.log('Snake details : ', snake.legs, snake.__proto__.legs);
To simply put, everything in JS is an object. When you create an object, it has 2 nested levels by default:
-> this
-> __proto__
Any property of your constructor goes to this. Any property on its prototype goes to __proto__. Since all objects are inherited from Object, there is a chain till global object.
All JavaScript objects inherit properties and methods from a prototype. Once it gets inherited, you can directly call or change the value of it.
function Animal() {
this.legs = 4;
}
var mouse = new Animal();
// mouse.__proto__.legs = 2;
//instead do this
mouse.legs = 2;
console.log(mouse.legs);

Why do I have to use the constructor.prototype in OOP Javascript?

I am learning OOP Javascript and I wonder why i need to use the constructor.prototype functionality. Can't I just put all the functionality i need in the construtor function like so:
function Class(){
this.x = x;
this.y = y;
this.--- = ---;
}
rather than:
function Class(){
this.x = x;
}
Class.prototype = {
constructor : Class,
y : y
}
Defining your methods/properties in the prototype will allow them to be shared between instances. Defining them in the constructor creates a new one for each instance.
You don't have to use the prototype... Use it if you want to share data. Typically you put methods on the prototype (because they don't change) and you set values on the instance itself.
One thing to beware, that often causes bugs, is defining mutable properties on the prototype. I've posted about this in Understanding prototypal inheritance
function Class(){}
Class.prototype = { obj : {}};
var a = new Class();
a.obj.x = 5;
var b = new Class();
console.log(b.obj.x); // 5
So you typically should define objects in the constructor (if you don't want them shared);
function Class(){
this.obj = {};
}
var a = new Class();
a.obj.x = 5;
var b = new Class();
console.log(b.obj.x); // undefined
Note that this is not a problem for primitives, because they can't be mutated, setting them on an instance just shadows the value from the prototype.
function Class(){}
Class.prototype = { val : 5};
var a = new Class();
console.log(a.val); // 5
a.val = 6;
console.log(a.val); // 6
var b = new Class();
console.log(b.val); // 5

defining method with prototype property and without prototype difference

please clarify the difference b/w this two codes
function Person(gender) {
this.gender = gender;
alert('Person instantiated');
}
Person.prototype.sayHello = function()
{
alert ('hello');
};
var person1 = new Person('Male');
var person2 = new Person('Female');
// call the Person sayHello method.
person1.sayHello()
and the second one is below where function define inside funciton (without prototype property)
function Animal(gender) {
this.gender = gender;
alert('animal instantiated');
this.sayToodle = function()
{
alert ('GOOOOOOO!!');
};
}
var Animal1 = new Animal('Male');
var Animal2 = new Animal('Female');
Animal1.sayToodle();
my more simple question are:
what is the difference?
define method inside or out side of a function. what is the effect?
if both same then which is the fine way to define this.
and what does prototype do?
Can we not define method of a obj out side of its function(CLASS)???
Defining a member inside the constructor (such as: this.name) gives only that instance of the object access to that member.
Defining a member inside the prototype allows all instances to "share" that property.
A way that helped me understand this was to define an array (or any other member that is not a method) inside the prototype, like so:
function Animal() {}
Animal.prototype = {
kids: [],
giveBirth: function() {
for(var i = 0; i < arguments.length; i++) {
this.kids.push(arguments[0]);
}
}
}
var cat = new Animal();
var giraffe = new Animal();
cat.giveBirth('kitten','another kitten','yet another kitten');
// cat.kids === ['kitten','another kitten','yet another kitten'];
// giraffe.kids === ['kitten','another kitten','yet another kitten'];
If you notice, the giraffe's kids were set (as kittens). Why is this? Because in this case, .giveBirth() accesses the prototype's kids array, which is shared by all instances.
What if we don't want to share the members, because the members are unique? You can do like so:
function Animal() {
this.kids = [];
}
Animal.prototype = {
giveBirth: function() {
for(var i = 0; i < arguments.length; i++) {
this.kids.push(arguments[0]);
}
}
}
var cat = new Animal();
var giraffe = new Animal();
cat.giveBirth('kitten');
// cat.kids === ['kitten']
// giraffe.kids == undefined
giraffe.giveBirth('baby giraffe');
// cat.kids === ['kitten']
// giraffe.kids === ['baby giraffe']
As you pointed out in the comments, part of how you decide to define the properties plays into memory usage; another part plays into what members you want to be "shared" across all instances.
To get a little more insight into prototypes (through understanding how new works), see What is the 'new' keyword in JavaScript?, on StackOverflow.
Here's a quote from there:
After a lot of searching, I have finally found out exactly what the
new keyword does, and it is 4 things:
It creates a new object. The type of this object, is simply object.
It sets this new object's internal, inaccessible, [[prototype]] property to be the constructor function's external, accessible,
prototype object.
It executes the constructor function, using the newly created object whenever this is mentioned.
It returns the newly created object, unless the constructor function returns a non-primitive value. In this case, that
non-primitive value will be returned.
Prototype members are shared among instances and members in the constructor function defined as this.something are instance specific.
When an instance need instance specific members (like Person.name) define it as this.name. When it can be shared (like a method sayName) define it on the prototype like: Person.prototype.sayName=function(){...
For more info on prototype and constructor functions you can check this answer.

JavaScript prototypal inheritance workaround

Here is an example:
var Box = function() {
this.id = generateUniqueId();
};
Box.prototype = {
add:function(parent) {
parent.appendChild(this.elm);
}
};
var NewBox = function() {
this.newThing = true;
};
NewBox.prototype = new Box();
NewBox.prototype.remove = function() {
this.elm.parentNode.removeChild(this.elm);
};
var a = new NewBox();
var b = new NewBox();
alert(a.id); // alerts 0
alert(b.id); // also alerts 0! :#
I would like to have a and b (basically each time I create a NewBox) have their own id. I understand that NewBox is using prototypal inheritance and is thus inheriting from a single instance of the generated id that it gets from Box, but I would like it so that each NewBox gets its own id without having to explicitly say that inside the NewBox constructor.
Maybe it's impossible or I'm doing something really wrong, so please help!
Thanks a lot!
In your example, the Box constructor gets executed only when you set the NewBox.prototype object.
You could workaround this by calling the Box constructor function inside NewBox with the Function.prototype.apply method, to set the this value and forward all the argument values, for example:
//..
var NewBox = function() {
Box.apply(this, arguments);
this.newThing = true;
};
//..
var a = new NewBox();
var b = new NewBox();
// assuming your `generateUniqueId` function
// increments a number
alert(a.id); // will alert 1
alert(b.id); // will alert 2
Now, each time the NewBox constructor is called to create a new object instance (new NewBox();), it will call the Box function to apply all its logic on it. This will help you to avoid repeating the logic of the parent constructor over and over.
The apply, is used call the "parent" constructor function setting the this value to the object instance that is being created by the NewBox constructor and we pass all arguments provided to this function.
Your example also shows a common problem, when you express inheritance relationship through NewBox.prototype = new Box(); the Box constructor gets called and it has side effects, this new object will be initialized and your generateUniqueId function will be executed for the first time, if you want to avoid that, you need to either use a temp constructor, just to make a new object that inherits from Box.prototype, or use the new ECMAScript 5 Object.create method for the same purpose, for example:
function inherit(o) {
function Tmp() {}
Tmp.prototype = o;
return new Tmp();
}
//.....
NewBox.prototype = inherit(Box.prototype);
Or:
NewBox.prototype = Object.create(Box.prototype);
In that way, you express the same inheritance hierarchy without running your Box constructor that first time, avoiding any side effect that it might cause.
At last but not least, whenever you replace a function's prototype property is always recommended to restore the constructor property of this new prototype object, otherwise it will point to the wrong function.
In your example, since you replace the NewBox.prototype with a new instance of Box, the NewBox.prototype.constructor property will point to Box, (your instances are affected, e.g. a.constructor === Box; // true) instead of to NewBox as you would expect, we need to set it back, e.g.:
NewBox.prototype = someObject; // as any of the examples above
NewBox.prototype.constructor = NewBox;
You could abstract those details into a function, as I did in the inherit function above:
function inherits(child, parent) {
var obj, Tmp = function () {};
Tmp.prototype = parent.prototype;
obj = new Tmp();
child.prototype = obj;
child.prototype.constructor = child;
}
//...
// instead of setting the `NewBox.prototype` manually
inherits(NewBox, Box); // "NewBox inherits from Box"
//...
Maybe it's impossible or I'm doing something really wrong, so please help!
You're doing something wrong.
If you want instance-specific values, initialize them in the constructor, not the prototype.
Matt Ball has the right idea. Instead try:
var Box = (function(){
var numberOfBoxes = 0;
function() {
this.id = numberOfBoxes++;
}
})();
Or in the case you want all your (different) classes to have unique ids:
var generateUniqueID = (function(){
var runningCount = 0;
return function (){
return runningCount++;
}
})();
var Box = function() {
this.id = generateUniqueId();
};
var NewBox = function() {
this.id = generateUniqueId();
this.newThing = true;
};

javascript prototype

I AM trying to understand js prototype property: my sample code
function Container(param) {
this.member = param;
}
var newc = new Container('abc');
Container.prototype.stamp = function (string) {
return this.member + string;
}
document.write(newc.stamp('def'));
function Box() {
this.color = "red";
this.member = "why";
}
Container.prototype = new Box();
Box.prototype.test = "whatever";
var b = new Box();
document.write(newc.test);
here the last line is undefined - even though Container's prototype is a Box and Box's prototype has a property test, why is the newc which refers to test in Box doesnt work? can any one please explain how the 'Prototype' works in my above context.
Thanks...
You are setting Container prototype to Box() after the newc instance was already created.
Reorder the statements as follows:
function Container(param) {
this.member = param;
}
function Box() {
this.color = "red";
this.member = "why";
}
Container.prototype = new Box();
Box.prototype.test = "whatever";
Container.prototype.stamp = function (string) {
return this.member + string;
}
//Here the containers prototype setup is complete.
var newc = new Container('abc');
document.write(newc.stamp('def'));
document.write(newc.test);
If sounds like you want to know WHY it is behaving the way it is, and not just "fix" the code. So here's what's going on.
As you saw, if you change the prototype of "Container", you will actually change the properties for new objects AND objects already instantiated. So:
function Container(param) {
this.member = param;
}
var newc = new Container('abc');
// setting a new property of the prototype, after newc instantiated.
Container.prototype.stamp = function (string) {
return this.member + string;
}
// This already-instantiated object can access the stamp function
document.write(newc.stamp('123')); // output: abc123
So there's no problem with the above, as long as you don't call the new method before it's defined. Now the next point. Add this to the above:
// Our Box object
function Box() {
this.color = "red";
this.member = "why";
}
Container.prototype = new Box();
var newd = new Container('fgh');
document.write(newd.stamp('456')); // output: ERROR
Error! But that makes sense, right? You totally wiped out the "Container" prototype and replaced it with the one from "Box", which has no "stamp" function.
I am going to assume you want "Box" to inherit from "Container". That would be logical from the naming convention. If you want to do that, replace the previous section with this:
// Our Box object
function Box() {
this.color = "red";
this.member = "why";
}
// This inherits from Container. Note that we can
// do this before or after we declare "Box"
Box.prototype = new Container();
Box.prototype.test = "Whatever";
var b = new Box("jkl"); // note: "jkl" is ignored because "Box" sets "member" to "why"
document.write(b.test); // output: Whatever
document.write("<br>");
document.write(b.stamp("345")); // output: why345
So now we have a "Box" that can call its own methods and parameters, and also call them from its parent "Container".
So the big picture is that an object will look at its own prototype for a method or something, and if it doesn't find it there it will look in the prototype of the thing it inherited from, and so on. The other big point is that setting something in the prototype makes it immediately available in all future AND current instances of that object.
An object does not contain a reference to its constructor which it uses to get at the prototype. If it did, then the code would work as you expected.
Instead, an object contains a reference to its prototype that is set when it is created.
From the language spec section 4.2.1:
Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype” property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain. When a reference is made to a property in an object, that reference is to the property of that name in the first object in the prototype chain that contains a property of that name. In other words, first the object mentioned directly is examined for such a property; if that object contains the named property, that is the property to which the reference refers; if that object does not contain the named property, the prototype for that object is examined next; and so on.

Categories