I need make one Super Function inherit the this of other function and make this other function inherit the methods from the Super Function, this is possible?
Explanation:
I have my BookingController and I want make the Controller function inherit the this.ME property:
BookingController.js:
var Controller = require('../api/Controller');
function BookingController() {
Controller.call(this);
this.ME = 'something here';
}
BookingController.prototype = new Controller;
BookingController.constructor = BookingController;
Controller.js:
function Controller() {
console.log(this); // EMPTY
};
Controller.prototype.myMethod = function() {
// Should work if BookingController try to access.
}
But nothing happens, there is no error and the BookingController can't find my myMethod and my Controller can't my this.ME
You use a bit wrong inheritance model. I suggest you to use something like
BookingController.prototype = Object.create(Controller.prototype);
BookingController.prototype.constructor = BookingController;
Related
I have a prototype:
var myClass = function() {};
I have a method on that class:
myClass.prototype.method1() = function() {
return x;
}
I then have a second method which I declare in the same way, but I want to access the result of method1() in it. But this doesn't work, and I'm not sure why...
myClass.prototype.method2() = function() {
return myClass.method1();
}
I get TypeError: myClass.method1 is not a function
Can anyone point out what's syntactically/conceptually wrong with this? And suggest any improvements?
Also I'm not 100% I'm using the terms 'class' and 'prototype' correctly in this instance. If anyone can correct the terminology, or point out any other terminology associated with this kind of process I'd appreciate it!
Thanks in advance.
var myClass = function() {};
This is a constructor and not a prototype. Here's a quick read explaining the difference.
You can call it using this. Here's the best place for a brush up.
const MyClass = function() {};
MyClass.prototype.method1 = function() {
return x;
}
MyClass.prototype.method2 = function() {
return this.method1();
}
Also, no need for brackets in function definitions of method1 and method2
That's because (using rough OO terminology), method1() is an instance method, and you're trying to call it as a static method.
const MyClass = function() {}; // MyClass is a constructor
MyClass.prototype.method1() = function() {
return x;
}
MyClass.prototype.method2() = function() {
return this.method1(); // Call it as an instance
}
or, alternatively:
const MyClass = function() {};
MyClass.method1() = function() { // "static" method
return x;
}
MyClass.prototype.method2() = function() {
return MyClass.method1(); // Call it as a "static"
}
Worth noting that this terminology is misleading, there are no static or instance methods (in fact, there are no methods in JavaScript, only functions, and properties that hold references to functions).
The JS oop has some difference between public and privileged methods.
myClass.method1(); is A static method calling. it's just like a normal function and has no relation with any myClass object instance.
So you need to call it using the Full namespace:
MyClass.method1()
I have this factory...
spa.factory("currentPageFactory", function() {
var pageDefinition = {};
pageDefinition.save = function(newPageDefinition) {
pageDefinition.value = newPageDefinition;
}
pageDefinition.read = function() {
return pageDefinition.value;
}
return pageDefinition;
});
...and this controller...
var pageDefinitionController = spa.controller("pageDefinitionController", ["currentPageFactory", function(currentPageFactory) {
currentPageFactory.save("foobar");
}]);
I have tested using the .read() function I created in this factory by including a definition in the factory of pageDefinition.value. I could read the variable using the getter just fine. The problem seems to lie in the setter.
I'm calling these functions like this...
/*Setter Call Example*/
currentPageFactory.save("blah");
/*Getter Call Example*/
this.foobar = currentPageFactory.read();
What am I doing wrong? Why is the setter not working?
I am attempting to change the behavior of a jquery plugin without actually changing the source. For the purposes of this question, I constructed a simple example that illustrates my problem. If a have script file that attaches a class instance generator to a global variable like this:
(function(){
window.newMyClass = function(){
return new myclass();
}
function myclass(){
var privateMethod = function(){
return "private";
}
this.publicMethod = function(){
return privateMethod();
}
}
})()
If I then get new instance of myclass with var instance = window.newMyClass(), is there any way to override the behavior of privateMethod on instance, such that instance.publicMethod() would call my overridden function? I was thinking I could subclass myclass, but since the myclass constructor is scoped to the immediately invoked function expression, I don't know how to do that.
Is it better just to change the plugin source? The problem with that is I'd have to host it myself instead of using a CDN, as well as re-implement the change every time an update is released.
I don't know if I understood well this. Probably not, because there is no mistery with that:
(function(){
window.newMyClass = function(){
return new myclass()
}
function myclass(){
var privateMethod = function(){
return "private";
}
this.publicMethod = function(){
return privateMethod();
}
}
})();
var instance = window.newMyClass();
instance.publicMethod = function(){
return "new method";
}
console.log(instance.publicMethod());
FIDDLE: http://jsfiddle.net/r9evbzd2/1/
In the code below, I've got two objects declared, with one object inheriting the properties and functions of another.
I want to use the super variable to call the methods of the object I inherited from. When I trace out itemEditor, I can see the function and it's methods correctly. When I try to access the method of itemEditor, it returns undefined.
What am I doing wrong? Is there a better way to do this?
var myObject = {
itemEditor : function (vars) {
this.editItem = function () {
alert("Editing Item");
}
},
recurringItemEditor : function (vars) {
myObject .itemEditor.apply(this, [vars]);
this.prototype = myObject.itemEditor.prototype;
var super = myObject.itemEditor
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(super);
console.log(super.editItem);
super.editItem.call(this);
}
}
Your code seems a little confused. On the one hand myObject.itemEditor is a constructor and therefore a function (myObject.itemEditor.apply(this, [vars])), and on the other you treat it like an object with a prototype (this.prototype = myObject.itemEditor.prototype;).
That's not even considering that super is a reserved keyword.
Your example may be simplifying something you are trying to do, but I don't see why you don't just use the usual prototype inheritance. That way you can still have a method in your local instance and call the prototype one within it if you want e.g.
recurringItemEditor : function (vars) {
this.prototype = new myObject.itemEditor(vars);
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(this.prototype);
console.log(this.prototype.editItem);
this.prototype.editItem.call(this);
}
}
I used your advice and it works well now. In regards to treating it like a function and an object, myObject .itemEditor.apply(this, [vars]); was still required in order for the object to inherit the properties of itemEditor. I should have made that clear in the original code. If there's a better way to do this, let me know.
var myObject = {
itemEditor : function (vars) {
var myVars = vars + "foo";
this.editItem = function () {
alert(myVars);
}
},
recurringItemEditor : function (vars) {
myObject .itemEditor.apply(this, [vars]);
this.prototype = new myObject.itemEditor(vars);
this.editItem = function () {
console.log("fn.recurringItemEditor.editItem");
console.log(this.prototype);
console.log(this.prototype.editItem);
this.prototype.editItem.call(this);
}
}
}
Basically I looking for the ability to attach methods to an executable function while using the javascript prototype method. The code below demonstrates want I'm talking about and the functionality I'm looking for, but it is really a hack. Notice I have a valid this object to attach variables along with a main and init function.
function create(){
var $this = {},
main = function(){
prototype.main.apply($this,arguments);
};
prototype.init.apply($this,arguments);
//Add additional prototype methods by brute force, ugly
for(i in prototype)-function(i){
main[i]=function(){
prototype[i].apply($this,arguments);
}
}(i);
return main;
};
var prototype = {
//called when you create the object
init:function(text){
console.log('init');
this.text = text;
},
//called when you call the object
main:function(){
console.log('main');
console.log(this);
},
method:function(){
console.log(this.text);
}
};
//create returns a function that also has methods
//the below line will call the init method
var fun = create('some variables');
//call main function
fun();
//call methods
fun.method();
I'm afraid I might be missing something obvious.
Here is the same functionality as above, but instead extends the global function prototype.
Extending the global properties is bad practice, so I am looking for a alternative solution.
Function.prototype = {
//called when you create the object
init:function(text){
console.log('init');
this.text = text;
},
//called when you call the object
main:function(){
console.log('main');
console.log(this);
},
method:function(){
console.log(this.text);
}
};
function create(){
var ret = function(){
ret.main.call(main);
};
ret.init.apply(main,arguments);
return ret;
};
//create returns a function that also has methods
//the below line will call the init method
var fun = create('some variables');
//call main function
//fun();
//call methods
fun.method();
Just as an obvious point, it doesn't appear you can use the typical new object approach because if you call new you can't return a separate value.
Any explanation or considerations would be great!
You can put your the prototype functions into the "constructor" body. This technically is what you are currently doing, but defining them explicitly rather than using a helper method is much cleaner. Then, you can further simplify your code using the following pattern for public and private variables and methods:
function Fun(text) {
// This is the main function
var fn = function () {
return 'main';
};
// Attach public variables and methods
fn.publicVariable = 'public';
fn.publicMethod = function () {
return text; // text is a "private variable"
};
// Do whatever initialization
console.log('init');
// Return the main function
return fn;
}
var fun = Fun('this is some text'); // "init"
fun() // "main"
fun.publicMethod() // "this is some text"
console.log(fun.publicVariable); // "public"
console.log(fun.text); // undefined
By "the JavaScript prototype method", do you mean using the Function.prototype property to implement inheritance? Or are you just trying to create functions that have an initializer and attached methods?
Your example does the latter, so I'll assume that's what you you're looking for. Does this do what you're looking for?
function create(text)
{
var main = function()
{
console.log('main');
console.log(this);
}
var init = function()
{
console.log('init');
main.text = text;
}
main.method = function()
{
console.log(main.text);
}
init();
return main;
}
//the following line will call init
var fun = create('some variables');
//call main
fun();
//call methods
fun.method();