Here is my code, class B inherits class A:
function A() {
this.msg = 'meuahah';
A.prototype.foo = function() {
alert(this.msg);
}
}
function B() {
A.call(this);
B.prototype.bar = function() {
A.prototype.foo();
}
}
a = new A();
a.foo(); // alerts 'meuahah'
b = new B();
b.bar(); // alerts 'undefined'
Why doesn't b.bar() display 'meuahah'?
Your prototypal inheritance is not quite right. This is probably more what you want to do:
function A() {
this.msg = 'meuahah';
}
A.prototype.foo = function() {
alert(this.msg);
}
function B() {
A.call(this);
}
B.prototype = new A();
B.prototype.bar = function() {
this.foo();
}
a = new A();
a.foo();
b = new B();
b.bar();
You can override foo in B like this:
B.prototype.foo = function() {
// Call the original foo method
A.prototype.foo.apply(this, arguments);
}
Because this is bound to the global object in that case.
You're calling this function
function() {
alert(this.msg);
}
when it is not bound to an object. So this will refer to the global object (which is window in the browser) and since that won't have a msg property, it will alert undefined.
When you call a = new A() you create a new object, add msg as a property, and set foo() on its prototype chain. So when you call a.foo() foo is bound to a and this refers to a.
In general you probably want something that looks more like this.
function A() {
this.msg = 'meuahah';
}
A.prototype.foo = function() {
alert(this.msg);
}
function B() {
A.call(this);
}
B.prototype = Object.create(A.prototype);
B.prototype.bar = function() {
this.foo();
}
You can read more about how this works in javascript from this question
The reason because b.bar displays undefined is because the this of the foo method is prototype, and prototype doesn't have a msg property.
You basically missed the main point, the inheritance. So, here the code revisited:
function A() {
this.msg = 'meuahah';
}
A.prototype.foo = function() {
alert(this.msg);
}
function B() {
A.call(this);
}
// Set the inheritance! Or better, the prototype's chain,
// so that any instance of B will have methods of A too
B.prototype = Object.create(A.prototype);
B.prototype.bar = function() {
// Because the inheritance, now B has the A's `foo` method too
this.foo();
}
// But... We can also override it.
B.prototype.foo = function() {
// do something
alert("override");
// then call the original one
A.prototype.foo.call(this);
}
Hope it helps to have a better idea about the objects and constructors. I will suggest to investigate on Object.create too, that it's really helpful; and the ES5 methods in general.
The reading Working with Objects it's also a good start, even if it's a bit old.
You're just called the A.prototype.foo function, so msg doesn't exist. Here is the output from the console when you console.log(this) inside A.prototype.foo
A {msg: "meuahah", foo: function}
A {foo: function}
The second one is when you call it from inside B, as you can see msg isn't present.
Related
can someone explain to me what I do wrong ?
I want to have a base Object (class) with standard functions and with B i want to overwrite standard functionality to be more specific, so i could change class B with C and have the same functions but underlying other code.
purpose of this all is that I need specific renderers if B or C does not have that function A should provide standard functionality.
in C# you have function overwrite stuff but i cant seem to figure out how it works in javascript.
thanks in advance.
var A = function () {
}
A.prototype = {
sup: function() {
console.log("sup");
},
doSome: function () {
console.log("doSomeA");
}
}
var B = function () {
A.call(this);
}
B.prototype = {
doSome: function () {
console.log("doSomeB");
}
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
var a1 = new B();
a1.doSome();
a1.sup(); // Not a function.
a1.sup(); // Not a function.
You're overwriting your prototype:
B.prototype = { ... }
B.prototype = Object.create(A.prototype);
That's exactly like overwriting any other variable - the latest applies.
And I learned this is the reliable pattern for inheritance:
function B() {
// Call super constructor
A.call(this);
}
// Clone inital properties and methods
B.prototype = Object.create(A.prototype);
// Extend the prototype
B.prototype.foo = "bar"
If I need a object into another for use in a function, which is the best?
function A() {
this.alert = function () {
console.log(b.value);
}
this.alert2 = function () {
console.log(this.value);
}
}
function B() {
this.value = 'test';
}
var a = new A();
var b = new B();
A.prototype.b = b;
// Option 1
`a.alert();`
// Option 2
`a.alert2.apply(b);`
I believe option 2 is better because only use the object (b) in one function.
The prototype is much easier, but I'd use it the other way round:
function B() {
this.value = 'test';
}
B.prototype.alert = function() {
console.log(this.value);
}
var b = new B();
b.alert();
If you want to use a function/method of a different object, you should give it a parameter (instead of using an implicit global b variable like in your a.alert function):
var a = {
alert: function(x) {
console.log(x.value);
}
};
a.alert(b);
or inherit from it when you have a method, like:
var a = {
value: "a test",
alert: function() {
console.log(this.value);
}
};
// =============================
function B() {
this.value = 'test';
}
B.prototype.alert = a.alert; // mixin inheritance
var b = new B();
b.alert();
There isn`t a best option, its about what you have to do.
The first option by putting b in its prototype makes A to be more coupled to b.
The 2nd one you are changing its contests.. you need to know what the function does, if you don`t have the documentation you may pass an object wich doesnt has a property needed for the function, so that is not a good choice to make an api for example.
Algo wouldn`t it be happier to set this.alert to a function which receives a parameter?
It all depende on your needs...
I want to do the following in Javascript
function A(){
this.B = function() { ... };
this.C = function() { <<I need to call B() here>> } ;
};
I have read the following way of method overloading, but I want to know whether professional programmers would do it this way. I.e. if you would only do this as an exercise or experiment or would actually do this in production code.
function foo(a, b, opts) {
};
foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});
Just call B() from inside C();
function A(){
B = function() {
// Do something here
}
C = function() { B(); }
};
Or, if you just want to create an alias
function A(){
B = function() {
// Do something here
}
C = B
};
The clean way would be :
var A = function() { };
A.prototype.B = function() { };
A.prototype.C = function() { this.B(); };
The prototype is just a static set of properties that is cloned inside every new instance you create.
The difference between what you're doing and this is that in your case, methods are created and added when you are in the "constructor" of the object, while with this method they already are properties of the object before you enter its "constructor", and are only parsed once (when you add them to the prototype) instead of being parsed everytime you create a new instance, which is faster.
I think, correct me if i'm wrong.
var A = function() {
// this scope is what i mean by "constructor".
};
I'm trying something like this:
(function() {
var Foo, foo;
Foo = function(proto) {
var obj, privateMethod, publicMethod;
privateMethod = function() {
return console.log("private", this);
};
publicMethod = function() {
console.log("public", this);
return privateMethod();
};
obj = Object.create(proto);
obj.bar = publicMethod;
return obj;
};
foo = new Foo({
baz: "dooz"
});
foo.bar();
}).call(this);
Obviously this is the object itself when publicMethod is called, but is set to the global object in the privateMethod. I know it can be solved by changing:
return privateMethod();
to:
return privateMethod.call(this);
I know that this get's lost when a function is nested in a function, but did not expect that case here. Do I encounter this JavaScript bug here or is there something that I simply do not understand yet?
Context (this), in javascript, is set by how a function is called, and is in no way a property of the function itself.
obj.bar = function() { console.log(this) };
obj.bar() // obj
obj['bar']() // obj
// But break the function off the object, and this changes
fn = obj.bar
fn() // window
What this example shows us is that the the dot syntax there sets this. Think of obj.bar() is syntax sugar for obj.bar.call(obj).
So your public method gets the right this, because of how it's called in external code.
foo.bar();
But your private method is invoked with no receiver at all.
return privateMethod();
So no context is assigned, and it defaults to the global object.
So given you are creating these functions in the constructor, you have some flexibility.
You could assign the proper value of this in the constructor to something else, and use that in your private functions. (Likely the best option)
var self = this;
privateMethod = function() {
return console.log("private", self);
};
Or if your JS target engine support Function.prototype.bind (not all do, sadly) you could do:
privateMethod = function() {
return console.log("private", this);
}.bind(this);
Which will return a function that has an assigned context, no matter what.
Or you could bind it manually yourself.
_privateMethod = function() {
return console.log("private", this);
}
Foo = function(proto) {
privateMethod = function() {
_privateMethod.call(this);
}
}
You're calling foo.bar(). This means the function bar() is called on foo, meaning this is foo inside bar().
In your case foo is a Foo object obj, and bar() is publicMethod.
When publicMethod() calls privateMethod(), there's no context, so this becomes the global this (window).
I have this type of code for prototypal inheritance in Javascript.
function A() {
this.a = 1;
}
function B() {
someEl.innerHTML(this.a);
}
B.prototype = new A();
However, I am wondering if there is a better way to do it, preferably one that brings the prototype declaration into the declaration of B.
I tried setting this.prototype in B, but it just showed this.a as undefined.
So, is there a better way to do this?
The prototype property should be used only in constructor functions, this.prototype doesn't makes sense because this just the new object instance, not the constructor.
Assign the prototype inside the constructor itself isn't a good idea, since that assignment will be executed each time you create a new object (by new B();).
Your code seems perfectly valid to me, the only thing that you should be aware of, is that if you replace the prototype property of a constructor, like you do it with B.prototype = new A(); the constructor property of the object instances of B, will point to A.
Usually is recommended to restore that property, e.g.:
function A() {
this.a = 1;
}
function B() {
someEl.innerHTML(this.a);
}
B.prototype = new A();
B.prototype.constructor = B; // restore the `constructor` property
var foo = new B;
foo.constructor === B; // true
Give a look to:
Constructors considered mildly confusing (article)
Setting javascript prototype function within object class declaration (SO question)
Try:
function A() {
this.a = 1;
}
function B() {
this.prototype = new A();
someEl.innerHTML(this.A.a); //notice A.a
}
function MyClass() {
this.initialize();
}
MyClass.prototype = {
initialize: function() { // adding a function name
this.some_var = "Blue"; // makes debugging easier
},
tell_color: function() {
alert(this.color);
},
color: "red"
}
var instance = new MyClass();
instance.tell_color();
This wasn't my idea, but I don't know anymore where I've found it.
Inheritance in JS is a little weird, but everyone else is correct that you should never put a prototype within a constructor. The point of prototyped functions/vars is so you only have a singular instance of that function for ALL instances of said class to use. Likewise it is good for class vars, a singular value which every instance will reference.
Really, you should make class B inherit from class A:
function B(){
this.object = new A();
}
B.prototype.a = function(){
return object.a;
}
which can be a little annoying since you must then create new getters/setters, buuuuuuuttttt, if you are feeling a little adventurous, you can build something like this......
function breakApart(what){
var functions = [];
var properties = [];
for(property in what){
if(typeof what[property] == 'function'){
functions.push({'name':property,'value':what[property]});
}else{
properties.push({'name':property,'value':what[property]});
}
}
var data = [
{'title':'functions','data':functions},
{'title':'properties', 'data':properties}
];
return data;
}
Add a few eval() calls and some logic and you can make this function build you new getters/setters/function references.