When to put self and when this in Ext-JS 4? - javascript

Consider the example:
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.app.Application-static-method-getName
Ext.define('My.cool.Class', {
constructor: function() {
alert(this.self.getName()); // alerts 'My.cool.Class'
}
});
My.cool.Class.getName(); // 'My.cool.Class'
What is the self referring to in this example?
How can I, in this documentation, know when to use this and when self and when this.self?
Why this is not working:
this.getName()
or
self.getName()
My thoughts about this are that self refers to the class of the object so the only reason I need to do this is because the getName() method is static so I'm (kinda) not calling it from object, but from class. Am I right? Am I? Ha? Ha? Am I? :D

this.self refers to the class object. It means that this.self === My.cool.Class. So you can instantiate new My.cool.Class object by invoking new this.self().
The reason why this.getName() doesn't work is because in JS static properties/methods are not available in instance.
Example:
var Class = function(){};
Class.prototype = {};
Class.staticMethod = function(){ alert('static method'); };
Class.prototype.instanceMethod = function(){ alert('instance method'); };
var instance = new Class();
Class.staticMethod(); // works
Class.instanceMethod(); // doesn't work
instance.staticMethod(); // doesn't work
instance.instanceMethod(); // works
Also static properties/methods are not available in sub class even in static context.
Example:
Ext.define('One', {
instanceMethod: function() { alert('Instance One'); }
});
Ext.apply(One, {
staticMethod: function() { alert('Static One'); }
});
Ext.define('Two', {
extend: 'One'
});
One.staticMethod(); // works
Two.staticMethod(); // doesn't work
The reason why getName method is available in My.cool.Class is because there are copied from Ext.Base class in ExtClass.create method (this class is private, it's not visible in API).
​

this.self does not work for recursive static methods, to call recursively to a static method you just have to use this (i.e. this.myCurrentRecursiveMethod(params))

Related

Calling one method of an object in another

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()

Change private class methods

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/

Prototype chain: call "super" method over multiple levels

I have got the following prototype chain
SuperSuperClass
SuperClass
Class
each with a method named do.
What is the common approach for calling the respective super class method?
For the moment I use <ClassName>.prototype.__proto__.<methodName>.call(this) but that looks odd.
Using the following code the console prints (as expected):
Class.prototype.do
SuperClass.prototype.do
SuperSuperClass.prototype.do
SuperSuperClass = function SuperSuperClass() {}
SuperSuperClass.prototype.do = function() {
console.log('SuperSuperClass.prototype.do');
};
function SuperClass() {
SuperSuperClass.call(this);
}
SuperClass.prototype = Object.create(SuperSuperClass.prototype);
SuperClass.prototype.constructor = SuperClass;
SuperClass.prototype.do = function() {
console.log('SuperClass.prototype.do');
SuperClass.prototype.__proto__.do.call(this);
};
function Class() {
SuperClass.call(this);
}
Class.prototype = Object.create(SuperClass.prototype);
Class.prototype.constructor = Class;
Class.prototype.do = function() {
console.log('Class.prototype.do');
Class.prototype.__proto__.do.call(this);
};
var objClass = new Class();
objClass.do();
JSFiddle
What is the common approach for calling the respective super class method?
Use <SuperClassName>.prototype.<methodName>.call(this). It's not only shorter, but also has the benefit of working in environments that don't support the non-standard __proto__ property.

Javascript Callable and prototype extendable Function

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();

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