We are using a oop architecture as the following, and we have a scope problem. We have the 'self' variable for saving the context, but when we call the function 'print' in the overridden class, we are using the 'self' variable instead of 'this', and we cannot override a base method.
Do someone knows how override this methods with this architecture?
var baseItem = function() {
var self = {};
self.a = function () {
console.log('base');
return 1;
};
self.print = function() {
return self.a();
}
return self;
};
var middleItem = function () {
var parent = baseItem();
var self = Object.create(parent);
return self;
}
var overrided = function () {
var parent = middleItem();
var self = Object.create(parent);
self.a = function() {
console.log('overrided');
return 55;
};
return self;
}
var obj = overrided();
overrided.print(); // This returns 1 instead 55, as we would want
Related
I found a Module pattern in JS:
<script>
var MODULENAME = (function(my, $) {
my.publicVar = "5";
my.publicFn = function() {};
return my;
}(MODULENAME || {}, jQuery));
</script>
However I cannot perform instantiation. Does the module pattern allow for that?
Instantiantion means basically that you'll run a function using new.
So maybe you're looking for this?
var Some = function (param) {
var somePrivateVar = 'private';
this.somePublicVar = 'public';
this.method = function () {
return param;
};
};
var some = new Some('abla');
console.log(some.method());
// some.somePrivateVar === undefined
// some.somePublicVar === 'public'
In your case MODULENAME is an object (object, not a function) with publicVar and publicFn. It's not meant to be instantiated the same way you wouldn't call new jQuery().
Your module object can contain anything. Perhaps you're looking for including a constructor in it:
var MODULENAME = (function(my, $) {
var privateVar = 10;
my.SomeConstructor = function() {
this.publicVar = 5;
}
my.SomeConstructor.prototype.someMethod = function() {};
my.SomeConstructor.prototype.getPrivate = function() { return 10; };
return my;
}(MODULENAME || {}, jQuery));
var instance = new MODULENAME.SomeConstructor();
instance.publicVar; // 5
instance.privateVar; // undefined
instance.getPrivate(); // 10
You can do this also with prototype Inheritance :
var MyClass = function(name)
{
//sharing name within the whole class
this.name = name;
}
MyClass.prototype.getName = function(){
return this.name;//now name is visible to getName method too
}
MyClass.StaticMethod = function()
{
console.log("Im Static");
// and since is not in prototype chain, this.name is not visible
}
var myclass = new MyClass("Carlos");
console.log(myclass.getName())//print "Carlos"
MyClass.StaticMethod()// print "Im Static"
myclass.StaticMethod() // error
Se all this article
I have three relatively similar knockout models in my application and I would like to extend a base model to combine common properties rather than repeat myself three times.
example
var ItemModel = function (item) {
var self = this;
self.order = ko.observable(item.order);
self.title = ko.observable(item.title);
self.price = ko.observable(item.price);
self.type = ko.observable(item.type);
};
var StandardItemModel = function (item, cartItemTypes) {
var self = this;
self.order = ko.observable(item.order);
self.title = ko.observable(item.title);
self.price = ko.observable(item.price);
self.type = ko.observable(item.type);
self.isInCart = ko.computed(function () {
return cartItemTypes().indexOf(item.type) > -1;
}, self);
self.itemClass = ko.computed(function () {
return self.isInCart() ? "icon-check" : "icon-check-empty";
}, self);
};
var CustomItemModel = function (item) {
var self = this;
self.order = ko.observable(item.order);
self.title = ko.observable(item.title);
self.price = ko.observable(item.price);
self.type = ko.observable(item.type);
self.icon = item.icon;
};
I would like to use ItemModel as a base class and just add the extra properties as necessary.
I think you can use ko.utils.extend like this
ko.utils.extend(self, new ItemModel(item));
inside the StandardItemModel
like this: http://jsfiddle.net/marceloandrader/bhEQ6/
I guess you can do something like this:
var StandardItemModel = function (item, cartItemTypes) {
var self = this;
self.standard = new ItemModel(item);
self.isInCart = ko.computed(function () {
return cartItemTypes().indexOf(item.type) > -1;
}, self);
self.itemClass = ko.computed(function () {
return self.isInCart() ? "icon-check" : "icon-check-empty";
}, self);
}
You can chain constructor calls using .call or .apply
function ItemModel (item) {
var self = this;
self.order = ko.observable(item.order);
self.title = ko.observable(item.title);
self.price = ko.observable(item.price);
self.type = ko.observable(item.type);
}
function StandardItemModel(item, cartItemTypes) {
var self = this;
ItemModel.call(this, item);
self.isInCart = ko.computed(function () {
return cartItemTypes().indexOf(item.type) > -1;
}, self);
self.itemClass = ko.computed(function () {
return self.isInCart() ? "icon-check" : "icon-check-empty";
}, self);
}
function CustomItemModel (item) {
var self = this;
ItemModel.apply(this, [item]);
self.icon = item.icon;
}
The advantage over ko.utils.extend (or similar methods from jQuery, underscore, etc) is that you are not creating an additional object just to grab references to its methods.
function MyBaseType() {
var self = this;
self.Id = 1
}
function MyComplexType() {
var self = this;
//Extending this class from MyBaseType
ko.utils.extend(self, new MyBaseType());
self.Name = 'Faisal';
self.MyComplexSubType = new MyComplexSubType();
}
function MyComplexSubType() {
var self = this;
self.Age = 26;
}
JSFIDDLE EXAMPLE
I've done something similar, with a lot of trial and error, but I got this to work for me:
var StandardItemModel = function (item, cartItemTypes) {
var self = this;
ItemModel.call(self, item)
}
You then need to add a prototyped constructor:
StandardModel.prototype = new ItemModel();
If you want to have common methods, then you need to add them to the base classes using prototype to add them, then call them in the higher class using:
ItemModel.prototype.methodName.call(self, parameters);
I have a Constructor function "Animals", that is namespacing some other Constructor functions, "Crocodile" and "Monkey":
var Monkey = function(Animals) {
this.Animals = Animals;
};
Monkey.prototype.feedMe = function() {
this.Animals.feed();
};
var Crocodile = function(Animals) {
this.Animals = Animals;
};
Crocodile.prototype.feedMe = function() {
this.Animals.feed();
};
var Animals = function(zoo) {
this.zoo = zoo;
};
Animals.prototype.feed = function() {
//feed the animal
};
Animals.prototype.Monkey = function() {
this.Animals = Animals.prototype;
};
Animals.prototype.Monkey.prototype = Monkey.prototype;
Animals.prototype.Crocodile = function() {
this.Animals = Animals.prototype;
};
Animals.prototype.Crocodile.prototype = Crocodile.prototype;
With the intention that I should be able to do the following:
var animals = new Animals("NY");
var monkey = new animals.Monkey();
monkey.feed();
I'm receiving an error that says that monkey.feed() is not a function. I'm assuming i'm doing something wrong with the way i'm inheriting the Monkey function inside the Animal constructor function but for the life of me I haven't been able to find the solution.
What is the correct method I should be using to namespace these functions?
I have seen quite some stuff, but abusing prototypes for namespaces, what the heck. What's wrong with a nice and simple:
var Animals = {
Crocodile: {
}
}
Or if you want the constructor way:
var Animals = function () {
return {
Crocodile: function () {}
}
};
var a = new Animals();
var c = new a.Crocodile();
I'm trying to understand pure prototype-based JavaScript and one specific thing I'm struggling with is reuse (inheritance).
For my project I landed this way of creating objects that can be reused.
// very generic prototype
var Apparatus = (function(){
var self = Object.create({});
self.state = false;
self.on = function() { this.state = true; };
return self;
})();
// more specific prototype
var Radio = (function(){
var self = Object.create(Apparatus);
self.frequency = 0;
self.setFrequency = function(f) { this.frequency = f; }
self.getFrequency = function() { return this.frequency; }
return self;
})();
I then want to "instantiate"/copy the Radio object, creating two different radios.
var kitchenRadio = Object.create(Radio);
kitchenRadio.state = false;
kitchenRadio.on();
var carRadio = Object.create(Radio);
carRadio.state = false;
console.log(kitchenRadio.state, carRadio.state);
// true false
This works, but will it continue to? Can anyone predict any unwanted outcomes?
Like #pimvdb said, remove state and this works well.
// very generic prototype
var Apparatus = (function(){
var self = Object.create({});
self.on = function() { this.state = true; };
return self;
})();
// more specific prototype
var Radio = (function(){
var self = Object.create(Apparatus);
self.setFrequency = function(f) { this.frequency = f; }
self.getFrequency = function() { return this.frequency; }
return self;
})();
I then use Object.create(Object, params) to instantiate it.
Unsure if I've phrased this correctly, but in the callback how do I reference the controls property of the base class?
This has been bugging me for some time and I usually work around it, but I'd be grateful if anybody can enlighten me on how I should do this properly.
var base = function() {
var controls = {};
return {
init: function(c) {
this.controls = c
},
foo: function(args) {
this.init(args.controls);
$(this.controls.DropDown).change(function() {
$(this.controls.PlaceHolder).toggle();
});
}
}
};
Much Obliged,
Paul
Use the power of closures:
var base = function() {
var controls = {};
return {
init: function(c) {
this.controls = c
},
foo: function(args) {
var self = this;
this.init(args.controls);
$(this.controls.DropDown).change(function() {
$(self.controls.PlaceHolder).toggle();
});
}
}
};
Although closures are preferred, you could also use jquery bind to pass an object along:
var base = function() {
var controls = {};
return {
init: function(c) {
this.controls = c
},
foo: function(args) {
this.init(args.controls);
$(this.controls.DropDown).bind('change', {controls: this.controls}, function(event) {
$(event.data.controls.PlaceHolder).toggle();
});
}
}
};
You need to leverage closures here.
var base = function() {
var controls = {};
return {
init: function(c) {
this.controls = c
},
foo: function(args) {
this.init(args.controls);
$(this.controls.DropDown).change(function(controls) {
return function(){
$(controls.PlaceHolder).toggle();
}
}(this.controls));
}
}
};