override backbone's view function - javascript

Suppose a backbone view such as
var Row = Backgrid.Row = Backbone.View.extend({
foo: function() {}
}
I want to redefine the foo function from outside of this source code.
Because the code above is itself a library as well.
How can I do it?

Inheritance in JavaScript is based on prototypes. Each class constructor has prototype property, where you can define methods of objects it will create.
Backgrid.Row.prototype.foo = function () {
// new code
}
It will replace existing implementation of foo for all Backgrid.Row instances, unless they have their own foo property.
var row = new Backgrid.Row();
row.foo = function () { ... }; // row now has it's personal `foo` implementation
I should tell that it is advised to create new class instead
var MyRow = Backgrid.Row.extend({ foo: function () {} });

Related

Access property in class from prototype override

Not sure if my question is worded properly. But basically I have a class, but I want to write a new method for it. Say my class looks like this:
class MyClass {
constructor () {
this.someProperty = []
this.someMethod = this.someMethod.bind(this)
}
function someMethod () {
// do something
}
}
Now, because I don't have direct access to this class, I am going to create a new method using prototype
MyClass.prototype.myNewMethod = function (params) {
// do something else
// how to access someProperty? And to the bind to MyClass?
}
But now say I want to access someProperty and also want to do the bind on this new method. How can I do that?
As a matter of fact is my method creation even correct to begin with? Anyway, what I want is for it to have the same access to the this inside the class. How can I do this?
I didn't understand what you want to do but so you can access it:
class MyClass {
constructor () {
this.someProperty = [];
}
someMethod = function() {
console.log(this.someProperty);
}
}
var cc = new MyClass();
cc.someMethod();

How to create instance of object from prototype method

Is it possible to create an instance of an object from it's prototype if the prototype is being used for multiple sublclasses?
For example, if I have:
var BaseClass = Backbone.Model.extend({
createNewForMap: function(map) {
// Here I would like to create a new instance of the
// class that the method is being called for.
}
});
var ClassOne = BaseClass.extend({});
var ClassTwo = BaseClass.extend({});
Then, somewhere in my application code, I want to be able to call:
var model = ClassOne.createNewForMap(map);
or
var model = ClassTwo.createNewForMap(map);
And have model be an instance of ClassOne or ClassTwo.
It is possible to define a static method on the BaseClass, that will serve as a factory function for it or any children classes, that inherit it.
Backbone.Model.extend allows you to specify so-called classProperties, that might be considered as something similair to static methods from conservative OOP programming.
var BaseClass = Backbone.Model.extend({}, {
// A static method for invoking constructor function.
createNewForMap: function(map) {
return new this;
}
});
var ClassOne = BaseClass.extend({
initialize: function() { this.foo = 'bar' }
});
var ClassTwo = BaseClass.extend({
initialize: function() { this.foo = 'buz' }
});
console.log(ClassTwo.createNewForMap().foo); // buz
<script src="//underscorejs.org/underscore-min.js"></script>
<script src="//backbonejs.org/backbone-min.js"></script>
You can use the constructor property to get a reference to an object's "class":
Object.prototype.constructor
Returns a reference to the Object function that created the instance's prototype. Note that the value of this property is a reference to the function itself, not a string containing the function's name.
So you can say things like:
createNewForMap: function(map) {
var obj = new this.constructor();
//...
}
and obj will be the same type of thing as this.
Demo: https://jsfiddle.net/ambiguous/avk4z6Le/

Javascript: Referencing object keys in nested prototype [duplicate]

I have built a large application using JavaScript prototype and inheritance.
But I am having a hard time organizing my code.
For example I have a class carousel which has many functions like this:
Carousel.prototype.next = function () {...}
Carousel.prototype.prev = function () {..}
Carousel.prototype.bindControls = function () {..}
I would like to organize my code like this :
Carousel.prototype.controls = {
next: function () { ... } ,
prev: function() { ... },
bindControls: function () { .. }
}
But this will cause the value of "this" being lost. I can keep track of it using a global instance but this will cause problems when the class is inherited for example In another file I have something like this to override parent class
BigCarousel.prototype.next = function () {...}
My inheritance is done like this:
Function.prototype.inheritsFrom = function (parentClass) {
if (parentClass.constructor === Function) {
//Normal Inheritance
this.prototype = $.extend(this.prototype , new parentClass);
this.prototype.constructor = this;
this.prototype.parent = parentClass.prototype;
}
else {
//Pure Virtual Inheritance
this.prototype = $.extend(this.prototype, parentClass);
this.prototype.constructor = this;
this.prototype.parent = parentClass;
}
return this;
};
So I can do:
BigCarousel.inheritsFrom(Carousel)
Does anyone know how can I work around the "this" value ?
You could make Controls a class of it's own:
var Controls = function (controllable_object) {
this.ref = controllable_object;
};
Controls.prototype.next = function () {
this.ref.foo();
}
// ..
var Carousel = function () {
this.controls = new Controls(this);
};
// ..
This doesn't allow you to override the implementation of Controls though. With more dependency injection you'd get something like:
var Controls = function (controllable_object) {
this.ref = controllable_object;
};
Controls.prototype.next = function () {
this.ref.foo();
}
// ..
var Carousel = function () {
this.controllers = [];
};
Carousel.prototype.addController = function (controller) {
this.controllers.push(controller);
};
// ..
var carousel = new Carousel();
carousel.addController(new Controls(carousel));
My inheritance is done like this:
$.extend(this.prototype , new parentClass);
Ouch. This is not inheritance (with new BigCarousel instanceof Carousel), but just copying properties. Maybe this is enough for you, but then you should call it mixin. Also, you should avoid using new for inheritance.
But this will cause the value of "this" being lost. How can I work around that?
It's impossible to have this point to the parent object with nested properties (as long as you don't want to explicitly set it every time). You have only two choices:
Forget it, and organize your methods by prefixing them (controlNext, controlBind, …)
Give each of your carousels its own controls object. For inheritance, make them CarouselControls instances for example. This especially fits well if those controls are quite independent from the carousel, and don't need to access the carousel they're attached to everywhere. If they are not, you still can pass a reference to the parent carousel into their constructor for example:
this.controls = new CarouselControls(this);
Also, for customizing the controls in different carousels, you might have to subclass the CarouselControls as well - or you prepare your Controls object to serve for different carousels in general, so that from BigCarousel you can
Carousel.call(this); // make this a carousel
this.controls.activate({big: true, fast: false}); // or something
You can use the .bind method of Function.
In Javascript Functions inherit from Object, so they have their own methods. One of those methods is .bind:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
Also you are doing inheritance wrong, the right way with raw Javascript is:
ChildClass= function() {
ParentClass.apply(this, arguments); //calling parent constructor
//constructor
};
ChildClass.prototype= new ParentClass();
Then you can simply do this on your constructor:
Courossel= function() {
ParentClass.apply(this, arguments); //calling parent constructor
this.controls.next.bind(this);
this.controls.prev.bind(this);
this.controls.bindControls.bind(this);
}
But I have to say that Frits suggestion is better, make the controls their own class and instantiate it on Carousel constructor passing a reference to your Carousel instance (the this keyword). Just don't call it ".ref", it's confusing.

Reference instance of parent class in prototype extension [duplicate]

I have built a large application using JavaScript prototype and inheritance.
But I am having a hard time organizing my code.
For example I have a class carousel which has many functions like this:
Carousel.prototype.next = function () {...}
Carousel.prototype.prev = function () {..}
Carousel.prototype.bindControls = function () {..}
I would like to organize my code like this :
Carousel.prototype.controls = {
next: function () { ... } ,
prev: function() { ... },
bindControls: function () { .. }
}
But this will cause the value of "this" being lost. I can keep track of it using a global instance but this will cause problems when the class is inherited for example In another file I have something like this to override parent class
BigCarousel.prototype.next = function () {...}
My inheritance is done like this:
Function.prototype.inheritsFrom = function (parentClass) {
if (parentClass.constructor === Function) {
//Normal Inheritance
this.prototype = $.extend(this.prototype , new parentClass);
this.prototype.constructor = this;
this.prototype.parent = parentClass.prototype;
}
else {
//Pure Virtual Inheritance
this.prototype = $.extend(this.prototype, parentClass);
this.prototype.constructor = this;
this.prototype.parent = parentClass;
}
return this;
};
So I can do:
BigCarousel.inheritsFrom(Carousel)
Does anyone know how can I work around the "this" value ?
You could make Controls a class of it's own:
var Controls = function (controllable_object) {
this.ref = controllable_object;
};
Controls.prototype.next = function () {
this.ref.foo();
}
// ..
var Carousel = function () {
this.controls = new Controls(this);
};
// ..
This doesn't allow you to override the implementation of Controls though. With more dependency injection you'd get something like:
var Controls = function (controllable_object) {
this.ref = controllable_object;
};
Controls.prototype.next = function () {
this.ref.foo();
}
// ..
var Carousel = function () {
this.controllers = [];
};
Carousel.prototype.addController = function (controller) {
this.controllers.push(controller);
};
// ..
var carousel = new Carousel();
carousel.addController(new Controls(carousel));
My inheritance is done like this:
$.extend(this.prototype , new parentClass);
Ouch. This is not inheritance (with new BigCarousel instanceof Carousel), but just copying properties. Maybe this is enough for you, but then you should call it mixin. Also, you should avoid using new for inheritance.
But this will cause the value of "this" being lost. How can I work around that?
It's impossible to have this point to the parent object with nested properties (as long as you don't want to explicitly set it every time). You have only two choices:
Forget it, and organize your methods by prefixing them (controlNext, controlBind, …)
Give each of your carousels its own controls object. For inheritance, make them CarouselControls instances for example. This especially fits well if those controls are quite independent from the carousel, and don't need to access the carousel they're attached to everywhere. If they are not, you still can pass a reference to the parent carousel into their constructor for example:
this.controls = new CarouselControls(this);
Also, for customizing the controls in different carousels, you might have to subclass the CarouselControls as well - or you prepare your Controls object to serve for different carousels in general, so that from BigCarousel you can
Carousel.call(this); // make this a carousel
this.controls.activate({big: true, fast: false}); // or something
You can use the .bind method of Function.
In Javascript Functions inherit from Object, so they have their own methods. One of those methods is .bind:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
Also you are doing inheritance wrong, the right way with raw Javascript is:
ChildClass= function() {
ParentClass.apply(this, arguments); //calling parent constructor
//constructor
};
ChildClass.prototype= new ParentClass();
Then you can simply do this on your constructor:
Courossel= function() {
ParentClass.apply(this, arguments); //calling parent constructor
this.controls.next.bind(this);
this.controls.prev.bind(this);
this.controls.bindControls.bind(this);
}
But I have to say that Frits suggestion is better, make the controls their own class and instantiate it on Carousel constructor passing a reference to your Carousel instance (the this keyword). Just don't call it ".ref", it's confusing.

Anonymous class with MooTools

Can I create the anonymous class(java term) using the MooTools js framework?
Suppose it should look like:
A = new Class({
invoke: function() {
alert('class');
}
});
a = new A({
invoke: function() {
this.parent();
alert('instance');
},
});
But I don't want to modify constructor interface around to accept additional properties.
Is there more comfortable way to define classes that are used not more than once?
You could define the class only within the scope it is going to be used in, which means the class won't be available outside that scope. For example, using a self-executing function:
(function() {
var MyClass = new Class({
invoke: function() {
alert('class');
}
});
var myObject = new MyClass({
invoke: function() {
this.parent();
alert('instance');
}
});
})();
(I've fixed up several errors in your code, including omitting the var keyword when declaring MyClass and myObject, and an extra , when initialising myObject.)

Categories

Resources