Javascript class inheritance, not a function - javascript

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"

Related

prototype vs apply in javascript

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...

javascript create new object by avoiding new keywords

JavaScript can create a object in many ways.
I try the following code to avoid new keyword to create a new Object of Class A.
My question is that A.prototype.init() here is whether equals new A()? is this good for practice, and why?
function A(){
}
A.prototype.init=function(){
return this;
}
var a = A.prototype.init();
console.log(a);
var a1=new A();
console.log(a1);
jsfiddle
All you're doing is returning the A.prototype object. You're not really initializing anything, and you're not using the result.
console.log(A.prototype === A.prototype.init()); // true
So unless you have a particular use in mind, I'd say, no it's not a good practice.
Not sure exactly why you want to avoid new, but in any case, you can change your constructor so that it can be called with or without new and still behave like a constructor.
function A() {
var ths = Object.create(A.prototype);
ths.foo = "bar";
return ths;
}
Now it won't matter if you use new. You're going to get a new object that inherits from A.prototype no matter what.
You can still use an .init() method, but you might as well just put the logic in the constructor.
Furthermore, you can easily create a factory that takes care of that little bit of boilerplate code.
function Ctor(fn) {
return function() {
var ths = Object.create(fn.prototype);
fn.apply(ths, arguments);
return ths;
};
}
So now you'd create your constructor like this:
var A = Ctor(function() {
this.foo = "bar";
});
You can avoid new by encapsulating your code with the module pattern and returning a function that calls the constructor, in other words:
var A = (function ClassA() {
// Constructor
function A(prop) {
this.prop = prop; // instance property
this._init();
}
// Public methods
A.prototype = {
_init: function() {
}
};
// Mini factory to create new instances
return function(prop) {
return new A(prop); // well, only one `new`
};
}());
Now you can create new instances without new:
var a = A('foo'); //=> A { prop: "foo", init: function }
Usually you catch direct function calls with instanceof:
function MyConstructor (a, b, c) {
if (!(this instanceof MyConstructor)) {
return new MyConstructor(a, b, c);
}
// ...
}
but there is no good reason to avoid using new. Object.create and other alternatives can have a significant performance impact.

Javascript Prototype Oriented Programming doubts

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".
};

javascript class members are undefined in child classes

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.

Is there a way to change the prototype from within a function in Javascript?

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.

Categories

Resources