Pass a function to a JavaScript class using struct annotation - javascript

Hi I need to create a class which can set properties as a function in JS, something like this:
var myClass = {
myFunction: null,
otherFunction : function ()
{
myFunction();
}
}
function initPage()
{
myClass.myFunction = function() { ... }
}
When i want use use myFunction, i can write: myClass.otherFunction();
Is it possible?

You need to use this to get to myFunction (which is after all, a property of the object):
otherFunction : function ()
{
this.myFunction();
}
What you have in the code in your question will look for myFunction in the closest available scope. The last thing it would look for is window.myFunction. As it is, it would probably error out (because there is no myFunction.
Again, the difference is that myFunction will look for scoped variables, whereas this.myFunction will look at properties of this, just like myClass.myFunction will look at properties of myClass (where myClass itself is a scoped variable).

If you call it as this.myFunction() it would work. But what's the benefit? What are you trying to achieve?
If you want to define a myClass as something to be instantiable, you have to define it like this:
var myClass = function(){
myFunction: null;
someFunction: function(){...};
otherFunction : function ()
{
this.myFunction();
}
}
Then instantiate it like a normal JavaScript object:
var myClassInstance = new myClass();
and call its methods:
myClassInstance.someFunction();
in this way, if you want to add a new method to your class declaration dynamically, you can use prototype property of your class. It's a reference to your class definition that let you alter your class definition dynamically.
myClass.prototype.myFunction = function() { ... };
and then call myFunction directly.
myClassInstance.myFunction();
For more information about using prototype concept, take a look at this resource:
Inheritance and The Prototype Chain

Related

Is it possible to append a method to a constructor/function without prototype property?

function DoIHavePrototype()
{
var a = 10;
}
CheckIt = new DoIHavePrototype();
DoIHavePrototype.prototype.GetFnName = function()
{
return "DoIHavePrototype"
}
alert(CheckIt.GetFnName())
In the above code,I observe that prototype is an in-built property for the function using which we can append property/method to a function.
But if I remove the prototype keyword in the above code like the following:
DoIHavePrototype.GetFnName = function()
{
return "DoIHavePrototype"
}
I don't get error in function definition but instead I get error while calling the method
alert(CheckIt.GetFnName()) as "CheckIt.GetFnName is not a function"
What does the JS interpreter assume this to be??
In order to be able to invoke some function a method on an object, there are 4 ways to introduce it to the object.
The first way is what you've done in your original code, which is to assign the function to the object prototype:
Foo.prototype.myFunc = function () { .... }
Another way is to assign it to this within the constructor.
function Foo() {
this.myFunc = function () { .... }
}
We can also assign it directly to the instance:
var foo = new Foo();
var myFunc = function () { .... }
foo.myFunc = myFunc
Finally, we can bind a function to the instance:
var foo = new Foo();
var myFunc = function () { .... }
var myFuncFoo = myFunc.bind(foo)
The last case is a bit special since we have a function that's not a property of the instance, but behaves like an instance method because it's invocation context is affixed to the instance.
The most common way of defining instance methods is assignment to the prototype. The prototype property on the constructor is what the instances inherit from, so that's where we put stuff. It's important to keep in mind that the instances inherit from the prototype property, not the constructor function. Assigning anything to a constructor property does not make it available as an instance property.
Assignment to this can sometimes be used if we want to have a method that's bound. For instance:
function Foo() {
this.boundMeth = this.meth.bind(this)
this.val = "foo"
}
Foo.prototype.meth = function () {
console.log(this.val)
}
This is useful if we want to pass instance.boundMeth() as a value to another function (e.g., event handler). In JavaScript, unlike many OO languages, methods are unbound:
// Using Foo from the previous example
function runner(fn) {
fn()
}
var obj = new Foo()
runner(obj.meth) // Logs `undefined`
runner(obj.boundMeth) // Logs `foo`
When assigning to the constructor prototype, you can assign in bulk:
Foo.prototype = {
meth1: function () { .... },
meth2: function () { .... },
}
If you use ES6, you can also use the class keyword:
class Foo {
myFunc() { .... }
}
This is the same as Foo.prototype.myFunc = function () { .... }.
If you append your function straight to the class it will generate so called static method which you can only call from you class like in Array.from.
So in your case you should call it using you class (not its instances) like so DoIHavePrototype.GetFnName();
you can read about this on MDN
This can also be done, in case if you still want to use it as instance method.
function DoIHavePrototype()
{
var a = 10;
this.GetFnName = function() {
return "DoIHavePrototype";
}
}
CheckIt = new DoIHavePrototype();
alert(CheckIt.GetFnName())

Javascript Library Object Method declarations

I am kind of a OO js noobie and am trying to create a new Javascript library the correct way but am struggling to understand how best to do this and make it work properly. I would like my library to self invoked so that an object ABC is instantiated as soon as the js library file is included in the html. However, then users should be able to call methods on that object in the html page.
I've tried a few different versions of the below code, but can't seem to get the prototype method for declaring methods to work properly. On my HTML page, I can call ABC.alert(); and it properly executes the alert message. However, when I try to call ABC.alert2(); which is using prototype inheritance which I understand is more memory efficient than just declaring methods right inside the object constructor, I can't seem to get that to work. I keep getting ABC.alert2 is not a function. I do see that my ABC object does have the proto property, but I can't seem to figure out how to define methods properly using prototype. Is it because I'm using a self invoked function? Should I not use a self invoked function and instead at the bottom of my library just create a new instance of my object manually with var ABC = new defineABC(); line?
jsbin link
Also copied below:
(function (window) {
'use strict';
function defineABC() {
var ABC = {};
ABC.alert = function() {
alert("hello this is working");
};
ABC.prototype.alert2 = function() {
alert("hello prototype is working inside constructor");
};
return ABC;
}
defineABC.prototype.alert3 = function() {
alert("hello prototype is working outside constructor");
};
if (typeof(ABC) === 'undefined') {
window.ABC = defineABC();
}
})(window);
ABC.alert(); //successful
ABC.alert2(); //fails
ABC.alert3(); //fails
You need to create an instance of your object to use the prototype methods.
var abc = new defineABC()
abc.alert2();
abc.alert3();
so u can define it in your code like this
if (typeof(ABC) === 'undefined') {
window.ABC = new defineABC();
}
You final code could look like this:
(function (window) {
'use strict';
function defineABC() {
}
defineABC.prototype.alert3 = function() {
alert("hello prototype is working outside constructor");
};
defineABC.prototype.alert = function() {
alert("hello this is working");
};
defineABC.prototype.alert2 = function() {
alert("hello prototype is working inside constructor");
};
if (typeof(ABC) === 'undefined') {
window.ABC = new defineABC();
}
})(window);
Since ABC is only created once per page, it's okay to declare methods right on the object.
It is also no need in factory function or IIFE. You colud instantiate an object as simple as that.
window.ABC = window.ABC || {
alert: function () {
alert("hello this is working");
}
};

How can I reference a `this` property within a method of `this`?

I append a services property to this:
function Client(){
this.services = {
'propertyName' : {}
};
and then append a method to this, in which I need to reference the services property of the instance of client:
function Client(){
this.services = {
'propertyName' : {}
};
this.someMethod = function () {
if (this.services['propertyName']) {
//do something
}
}
}
var clientName = new Client();
But this.services - line 6 is undefined. How can I use a property assigned to this in a method assigned to this? It seems like it should be possible because by the time that method is called by the constructor, the services property will exist for the object. Is this a language limitation? Is it possible? Should it be?
But this.services - line 6 is undefined.
That will depend entirely on how you call someMethod. If you call it like this:
clientName.someMethod();
...it'll be fine, because this within the call will be the object created by new Client that you've put the services property on. But in JavaScript, this is not a fixed thing with normal functions, it's set by how you call the function. So:
var f = clientName.someMethod;
f();
...would fail, because this wouldn't be the object you expect. (This isn't true of ES6's new "arrow" functions, which get this from where they're defined, not how they're called.)
You mostly see this when functions are used as callbacks:
doSomething(clientName.someMethod);
...because doSomething doesn't know what object to use as this.
You can fix it by using Function#bind:
doSomething(clientName.someMethod.bind(clientName));
or similarly:
var f = clientName.someMethod.bind(clientName);
f();
Function#bind creates a new function that, when called, will call the original with this set to the argument you give it.
Just to flesh out my ES6 comment above: In ES6, if you had:
function Client(){
this.services = {
'propertyName' : {}
};
this.someMethod = () => { // <== ES6 "arrow" function
if (this.services['propertyName']) {
//do something
}
}
}
...it wouldn't matter how you called someMethod, this would be what it is where that function was created. V. handy. :-)

Javascript function object with this reference to itself

I can't seem to find an example of what I'm trying to achieve, although I'm sure it has been done many times before...
I want to create an object which will have a set of properties and member functions but that I can also call directly. In the same way the jQuery object allows you to call $("selector") or $.method(...)
Here's a slimmed down version of what I'm trying to achieve :
var foobar = function(param) {
return "FOO : " + this.lookup(param);
}
foobar.vals = {
1: "one",
2: "two"
};
foobar.lookup = function (param) {
return "BAR : " + this.vals[param];
}
foobar.lookup("1")
// returns "BAR : one"
foobar("1")
// returns error since 'this' points to global scope
// I'd want it to return "FOO : BAR : one"
I've also tried various approaches with function prototype but can't seem to find a method which gives me everything I want...
var foobar = function(param) {
return "FOO : " + foobar.lookup(param);
}
will return you what you want
To understand this, maybe you should take a look at the basics of JavaScript. What are functions how to instanciate an object and what are objects...
To get something like JQuery this is not very difficult, the JQuery main object is simply a function which also has "static" functions.
to declare a variable as function you do
var myFunc = function(){};
to use the variable and extend it with static stuff you simply assign it via
myFunc.staticFunc = function(){};
this doesn't mean that myFunc.staticFunc can be accessed with this in any instance of myFucn because you didn't add the function to the prototype...
To define a class like object which can be instanciated you also define it as function and then extend the prototype. Prototype is your class definition which is used to construct the object's instance:
myFunc = function(){
// ctor
this.lala = "blub";
} ;
myFunc.prototype.objectFunc = function() {
return this.lala;
}
now the object myFunc has a function objectFunc. I have to initialize it with new...
alert(new myFunc().objectFunc());
instances can access itself with this...
To do something like jquery you'll have to do some tricks. Your global variable must be a function which returns an instance of your "real" object, which can implement whatever...
Then you can call your variable as if it is a function, e.g. myFunc()...
Hope the following example makes it more clear how this works: (can be found on jsfiddle)
(function ($) {
var myRealObj = function (outId, printText) {
this.text = printText;
$("#" + outId).append("<li>" + this.text + "</li>");
};
myRealObj.prototype.objectFunc = function () {
return this.lala
};
var myFunc = function (out, txt) {
return new myRealObj(out, txt);
};
myFunc.someFunc = function () {
myFunc("out", "myFunc.someFunc got called");
};
myFunc.static = {};
myFunc.static.someFunc = function () {
myFunc("out", "myFunc.static.someFunc got called");
};
window.$$ = myFunc;
})($);
$$("out", "test obj function");
$$.someFunc();
$$.static.someFunc();
You could add:
foobar = foobar.bind(foobar);
to make the variable refer to a bound version of the function. Any call to the (updated) "foobar" would have this bound to the original function object. You'd also have to mirror the properties if you wanted to get at them directly, which is sort-of a mess.
In the jQuery implementation, there's a separate internal function that handles the basic routing of the master $() function.
Note also that the "global" $.whatever() functions don't really have much to do with the set of methods supported by jQuery instances (objects returned from the $() function). The $ object just serves as a namespace so that those global utilities don't pollute the global (window) namespace.
you declare var foobar = function(param) {... in the global scope so this will always be a window

Javascript methods use

I am trying to create a class in JavaScript that would be inherited and than some of its methods would be overridden.
I am using the following structure :
function MyClass()
{
this.myvar = null;
this.someotherVar = { someFunction: function(a,b){ function1(a,b); })
}
// some functions
MyClass.prototype.functionA = function() {..}
MyClass.prototype.functionB = function() {functionC();}
//some functions that would be overrided
MyClass.prototype.function1= function() {...}
MyClass.prototype.functionC= function() {...}
Now I have 2 problems:
Might functionC be a problem to use in functionB because it is defined afterwards?
How can I relate to function1 inside someFunction in the right way?
1. Might functionC be a problem to use in functionB because it is defined afterwards?
No. You just have to call it properly:
function() { this.functionC(); }
// ^^^^^
otherwise the function won't be found.
Of course you also have to make sure that functionB is only called once functionC is defined.
2. How can I relate to function1 inside someFunction in the right way?
A tiny problem is that someFunction is not a method of the instance but of another object. To still call the correct function1, you can store a reference to the instance in a variable:
function MyClass() {
var self = this;
this.myvar = null;
this.someotherVar = {
someFunction: function(a,b){
self.function1(a,b);
}
};
}

Categories