Access parent property inside object literal - javascript

We have a JS framework that lets us set up "modules". Each module is added by calling the addModule method and passing a literal object that contains required properties about the module as well as optional methods. Example:
framework.addModule({
id: "test-module",
init: function () {
//stuff to do when initializing like set up jQuery bindings
$("div").click(function () {
// need access to literal object so I can call:
something.utility1();
});
},
utility1: function () {
something.utility2();
},
utility2: function () {
// need access to literal object so I can call:
}
});
I'm trying to figure out the easiest way to make the object itself available to any code, at any level, inside the object (in place of "something").
The best I've been able to do is to add a this: this property to the object and then inside of methods I can put var module = this, which works but requires that variable to be added to each module. I'd like to see if there's another way that wouldn't require adding a variable to each method. Thanks.
Thanks for the comments and, zzzzBov, thanks for your suggestions.
However, it looks like the below code will work best for my needs. The devs on my team are writing a lot of these modules and I need the solution to be clear to them. Having to call $.proxy could make it less clear. I was hoping to avoid having to put var module = this in each method, so it would be cleaner, but it seems that it's not possible without it.
framework.addModule({
id: "test-module",
init: function () {
var module = this;
$("div").click(function () {
module.utility1();
});
},
utility1: function () {
var module = this;
module.utility2();
},
utility2: function () {
}
});
If anyone has a cleaner solution, let me know.

jQuery has a proxy method which will bind the function to a specific context. This would turn your event binding into:
$('div').click($.proxy(this, 'utility1'));
Alternatively, instead of using an object literal to instantiate the module object, you could instantiate an anonymous function:
framework.addModule(new function () {
this.id = 'test-module';
this.init = function () {
$('div').click($.proxy(this, 'utility1'));
};
this.utility1 = function () {
...more code...
};
this.utility2 = this.utility1;
});

Related

Cannot access function inside function javascript

I'm trying to clean my code a bit, so I create some small objects or libraries (call it how you want) like:
function myLib() {
this.get = function() { ... };
...
};
Problem is when I try to call it like myLib.get(). It throws the following error:
Uncaught TypeError: myLib.get is not a function
I've tried to encapsulate the call into $(document).ready(), but it did not help.
Can you help me, please?
Thanks!
myLib is used for "libary", and you want to call this "get" method of libary.
Static instance is better in your case.
const myLib = {
get:function(){},
get2:function(){}
...
};
myLib.get();
myLib.get2();
so I create some small objects or libraries (call it how you want)
In your case you are creating a constructor, myLib is a constructor and not just a function, and you can't access a function's properties and methods directly that's why you got the Exception.
So you need to get an instance of myLib in order to call the get method or to access any of its members(methods).
function myLib() {
this.get = function() { console.log("get called!!"); };
};
let lib = new myLib();
lib.get();
Note:
And from the MDN Reference for Functions you can see that:
The this keyword does not refer to the currently executing function, so you must refer to Function objects by name, even within the function body.
You should use myLib as a constructor ie:
var lib = new myLib();
lib.get();

BackboneJS - using keyword this inside view

If i want to call a function inside Backbone view, i have to call it like this.
this.functionName()
If i want to call the same function inside forEach Or jquery's each function, this refers to different context here. So i need to hold view's reference to some other variable and i have to use it something like below.
refresh: function () {
var view = this;
$("#list").each (function () {
view.functionName();
})
}
And finally, if i look at my view, i declare like this almost all of my functions. Did anyone find better alternative for this?
Since you are using Backbone, you would already have underscore. Using underscore you can specify context for each call.
refresh: function() {
_.each($("#list"), function() {
this.functionName()
}, this))
}
This is indeed common in Javascript, by convention they call the variable that:
var that = this
jQuery also has a proxy() function which will call a function and set the context variable (this) to something you assign: http://api.jquery.com/jQuery.proxy/
So you could do something like this:
refresh: function() {
$("#list").each($.proxy(function() {
view.functionName()
}, this))
}
But most of the times it is even more unreadable. To be honest I never use proxy() and I can't think of a good example of when to use it, but it's nice to know of it's existance, might you ever need it.
The usuals are defining either var that = this; or var self = this; or var _this = this;
The Airbnb JavaScript Style Guide which I find very sane advocates the latter. (you may want to scroll a little to find the meat).

Why can't my jQuery.Widgets namespace be accessed?

I've been reading alot about the advantages of using the jQuery.Widget Factory for my plugins. One of the capabilities touted is how the jQuery.widget creates a namespeace for your widget. This is attractive, as I can maintain my current namespacing (naturally) within the jQuery context.
THE PROBLEM:
I keep getting "$(".myWidget").namespace.newWay is not a function" error.
For the following element...
<div class="myWidget"></div>
THIS EXAMPLES CODE WORKS:
While nice...this is NOT what I am trying to achieve...as I still want my namespace to be honored.
var workingVersion = {
_init: function () { /* Do Something*/ }
};
$.widget("ui.workingVersion", workingVersion);
$(document).ready(function () {
$('.myWidget').workingVersion();
});
HOWEVER, MY CODE FAILS:
var namespace = namespace || { };
;namespace.newWay = (function ($, window, document, undefined) {
return function (options) {
var self = this;
this._create = function () {
// Do something
},
this._init = function() {
// Do something
},
this.publicFunction = function () {
// Do something
};
};
})(jQuery, window, document);
$(document).ready(function () {
$.widget("ui.namespace.newWay", namespace.newWay); //<-- Namespace does get appended
$('.myWidget').namespace.newWay({ type: 'testing' }); //<-- But still fails here
});
MY QUESTION IS:
Why does it fail?
RELATED READING:
Understanding jQuery UI widgets: A tutorial
Tips for Developing jQuery UI 1.8 Widgets
This answer comes a bit late, maybe, but I was struggling with the same thing and had to do some reading.
$() in General
The $() instance is a no-namespace shortcut list to different functions spread out over different namespaces. You can add more functions to this shortcut list by writing:
$.fn.myFunction = function() {
...
};
Which then will be accessed by calling
$("...").myFunction();
If you add two functions by the same name the latter one will overwrite the first one.
Widgets
When you create a widget with a namespace it's created with it's namespace, as you would expect, but to $() it's added without it's namespace, as a simplified shortcut to your real widget-with-shortcut. This is done using $.widget.bridge(). You can therefore create your own namespaced link to $() by writing like this:
$.widget.bridge("namespace_myFunction", $.namespace.myFunction );
And then access your widget like this:
$("#myDiv").namespace_myFunction();
To use a widget directly with it's original namespace you can instead invoke it like this:
$.namespace.myWidget(
{
option1: "",
option2: ""
},
$("#div")
);
Hope this will clarify a little...

Javascript Prototype not Working

Hi I don't know whether this is my mistake in understanding Javascript prototype object ..
Well to be clear I'm new to the Javascript singleton concept and lack clear cut knowledge in that but going through some referral sites I made a sample code for my system but it's giving out some errors which I couldn't find why so I'm asking for your help. My code is:
referrelSystem = function(){
//Some code here
}();
Prototype function:
referrelSystem.prototype.postToFb = function(){
//Some Code here
};
I get an error saying prototype is undefined!
Excuse me i thought of this right now
EDIT
I have used like this:
referrelSystem = function(){
return{
login:getSignedIn,
initTwitter:initTw
}
};
Is this causing an issue?
A typical way to define a JavaScript class with prototypes would be:
function ReferrelSystem() {
// this is your constructor
// use this.foo = bar to assign properties
}
ReferrelSystem.prototype.postToFb = function () {
// this is a class method
};
You might have been confused with the self-executing function syntax (closures). That is used when you would like to have "private" members in your class. Anything you declare in this closure will only be visible within the closure itself:
var ReferrelSystem = (function () {
function doSomething() {
// this is a "private" function
// make sure you call it with doSomething.call(this)
// to be able to access class members
}
var cnt; // this is a "private" property
function RS() {
// this is your constructor
}
RS.prototype.postToFb = function () {
// this is a class method
};
return RS;
})();
I would recommend that you study common module patterns if you're looking into creating a library.
Update: Seeing your updated code, the return from referrelSystem won't work as expected, since return values are discarded when calling new referrelSystem().
Rather than returning an object, set those properties to this (the instance of referrelSystem that gets constructed):
var referrelSystem = function () {
// I assume you have other code here
this.login = getSignedIn;
this.initTwitter = initTw;
};
I don't think you intend to immediately execute the functions, change them to this:
var referrelSystem = function(){
//Some code here
};
(+var, -())
Same with the prototype function:
referrelSystem.prototype.postToFb = function(){
//Some Code here
};
(Here you don't need the var, because you're assigning to something that already exists.)
A function should return to work as
prototype
property.
Take a look at this example here

Javascript: which function structure to use

I was reading an article about Javascript's best practices, and kinda got confused about which function structure to use...
I guess it might have an impact on the scope of the variables and functions, but which one of these structures would you use (and which is considered the best practice)?
Structure 1: use the object literals.
var obj1 = {
_myvar : 'myval',
init: function() {
this.function1();
this.function2();
},
function1: function() {
alert('function1');
},
function2: function() {
alert('function2');
}
};
obj1.init();
Structure 2: Wrap the code in an auto-executing function.
(function(){
var _myvar = 'myval',
function1 = function() {
alert('function1');
},
function2 = function() {
alert('function2');
},
init = (function() {
function1();
function2();
}) ();
}) ();
You use the self-executing anonymous function when you don't want others to interfere with your code and/or don't want to use any global variable. If you might want to use those functions/objects/whatever somewhere else, you would want to use the first one.
"Structure 1" is appropriate when you need access to the methods and variables in an object from other parts of your code. That format should always be your preference when you're writing library code that's meant to be reused elsewhere.
"Structure 2" is appropriate when you don't want to share your code with other parts of the application, and so you want to protect the variables and functions from any interference from elsewhere.
I have found Christian Heilmann's Revealing Module Pattern to be quite useful. (Scroll down to the last "green screen" code sample on his page.)
With is pattern, you can create all of your methods/functions privately in an anonymously executed function and then choose your public interface via the returned object.

Categories