I am writing a module that needs to call internal functions within the module and make use of variables in the constructor. To call these functions internally I could either use the variable mycode or use the keyword this. However using mycode means using a global variable and this can be overwritten by parts of my functions. This is a simplified model of my module's structure:
// app.js
const MyCode = require('mycode.js');
var mycode = new MyCode();
mycode.function1($(html));
// mycode.js
module.exports = class {
constructor() {
this.alertUrl = true;
}
function1(html) {
html.find('a').each(function () {
var url = $(this).attr('href');
this.function2(url); // this is now overridden by jquery
});
}
function2(url) { if (this.alertUrl) alert(url); }
}
I am looking for a solution that would work like myModule.function2(url);, where myModule is only available to functions inside the module.
You can use an arrow function instead, so that the this reference is inherited from the outer scope, rather than being altered by the each callback:
html.find('a').each((_, elm) => {
var url = $(elm).attr('href');
this.function2(url);
});
Another (less elegant) option is to save a reference to the instance before calling the each:
function1(html) {
var self = this;
html.find('a').each(function () {
var url = $(this).attr('href');
self.function2(url);
});
}
The problem doesn't really have anything to do with modules, just the calling context of functions.
you can use async function with export like this...
const function_name = async () => {
};
export default function_name ;
Related
When calling a function in the module in this way
app.get("/api/sessions/oauth/google", (req, res) => {
return google_callback.googleOAuthHandler(req, res);
});
this points to the module and another function in the module can be accessed using this
googleOAuthHandler : async function (req, res) {
const code = req.query.code.toString();
const {id_token, access_token} = await this.getGoogleOAuthToken(code);
}
However passing the function as a parameter changes this to global and this.getGoogleOAuthToken becomes undefined
i.e when doing
app.get("/api/sessions/oauth/google", google_callback.googleOAuthHandler);
how would i access getGoogleOAuthToken in googleOAuthHandler in google_callback module when using this way
app.get("/api/sessions/oauth/google", google_callback.googleOAuthHandler);
When passing function this way this doesn't mean the module. So this.getGoogleOAuthToken doesn't work.
however we can use module.exports.getGoogleOAuthToken to access the function within the same module. Using module.exports.getGoogleOAuthToken also works in the first example.
Alternatively if you don't like module.exports to call the function you can place line const _this = this; at the top of the file or const _this = module.exports = { ... } and use _this.function to call a function inside the module.
Also just noticed that in the first example this.function only works because i'm using this syntax.
module.exports = {
func1 : function(){},
func2 : function(){}
}
when exporting with
module.exports.func1 = function(){}
module.exports.func2 = function(){}
this cannot be used to access the other function
I'm trying to call a function inside another function in javascript, actually trying to call populateCurrencies() inside startApp(). What am I doing wrong?
const startApp = () => {
const populateCurrencies = ();
function populateCurrencies() {
alert(return this.option.value + " " + this.option.textContent);
}
const startApp = () {};
You are using a invalid syntax.
You declare functions like this (with arrow function expression).
const myFunc = () => {
// Code to run here...
}
And you call your function like this.
myFunc();
Not const myFunc = () {}; like it is in your example.
Also, const is a constant, you can't have multiple constants with the same name, so that's an error as well. And if you want to reassign values to a variable you have to use let instead. But that's beside the point since you won't need those extra variable declarations that you have now when you call the functions.
I've the following javascript code
var globalConfiguration = null;
function loadFile(filePath) {
}
function onLoadPage() {
}
function getConfiguration() {
}
function process() {
}
I want to use IIFE to encolose all my functions in a closure to avoid cluttering the global name space,so I wrote :
(function(window){
var globalConfiguration = null;
function loadFile(filePath) {
}
function onLoadPage() {
}
function getConfiguration() {
}
function process() {
}
});
However, I do not understand this notion very well, now in my HTML page how would I call my function onLoadPage?
You can't without putting it in the global namespace somehow.
My recommendation to structure code like this:
function ExampleHelper() {
(function(scope) {
scope.globalConfiguration = null;
scope.loadFile = function(filePath) {
};
scope.onLoadPage = function() {
};
scope.getConfiguration = function() {
};
scope.process = function() {
};
})(this);
}
var foo = new ExampleHelper(); // "foo" now contains all of your functions
foo.onLoadPage();
Now that you have enclosed the module, you need to decide what you want to expose to the outside world. Anything you want to expose, you can export. Also, you need to decide what context (in this case, window) that you want to attach to. Then pass the context in right away (thus completing the IIFE).
For example:
(function(window){
var exports = {};
var globalConfiguration = null;
function loadFile(filePath) {
}
function onLoadPage() {
}
function getConfiguration() {
}
function process() {
}
exports.getConfiguration = getConfiguration;
window.myModule = exports;
})(window);
Attaching to the passed in window object is one way to export things out in a controlled fashion. So, you do need to pass the context (in this case window) to the IIFE. Perhaps, window will not always be the context for the call.
After running this code, myModule will be available on the global scope.
You can set your function to window.onload callback.
(function(window) {
var globalConfiguration = null;
window.onload = onLoadPage;
function loadFile(filePath) {}
function onLoadPage() {
alert('hello world');
}
function getConfiguration() {}
function process() {}
}(window));
This is called chaining of functions/methods and is usually done for better readability of the code and to avoid the usage of temporary variables to hold the return value of each function.
Check this post on chaining methods which helped me to understand the chaining better.
I see you wanted to use closures to avoid cluttering the global object. However, do note that we write functions for reusability. Though you create a closure, ensure that your methods inside the outer function are abstracted such that they can be used by other parts of the code.
For ex: from your code, you have a loadFile method which could be reused.
Now to see how you can use the methods you described in a chain.
Assumptions: (since i don't know why you wrote those methods, i am making some assumptions).
loadFile(filepath) - returns a file object
onPageLoad() - once the page is loaded, it returns the object or id of the input file
getConfiguration() - gets the file path
process() - process the file
onPageLoad().loadFile(getConfiguration()).process();
The important part is that the scope of the object is set correctly in the chaining. In order to do this, each method must return the reference to appropriate object.
Hope this helps.
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);
}
};
}
I'm developing a web framework for node.js. here is the code;
function Router(request, response) {
this.routes = {};
var parse = require('url').parse;
var path = parse(request.url).pathname,
reqRoutes = this.routes[request.method],
reqRoutesLen = reqRoutes.length;
..... // more code
};
Should I change all the var to this, like so:
function Router(request, response) {
this.routes = {};
this.parse = require('url').parse;
this.path = this.parse(request.url).pathname;
this.reqRoutes = this.routes[request.method];
this.reqRoutesLen = this.reqRoutes.length;
..... // more code
};
Any comments?
Add properties to this when you want the properties to persist with the life of the object in question. Use var for local variables.
edit — as Bergi notes in a comment, variables declared with var don't necessarily vanish upon return from a function invocation. They are, and remain, directly accessible only to code in the scope in which they were declared, and in lexically nested scopes.
It on depends what you want to do.
If you declare the variables with var, then they are local to the function and cannot be accessed outside.
If you assign the variables to this, then they will be set as properties of the context object the function is called on.
So if e.g. if you write:
var obj = new Router();
then obj will have all the variables as properties and you can changed them. If you call
somobject.Router()
then all the variables will be set as properties of someobject.
You can think of properties hung from this sort of like instance variables in other languages (sort of).
It looks like you're creating a constructor function and will likely add some prototype methods. If that's the case, and you need access to routes, you've got it, but not path.
Router.prototype = {
doSomething: function(){
this.routes; // available
path; // not available
}
}
Using var in the constructor is usually used for private variable while using this. is used for public variable.
Example with this. :
function Router() {
this.foo = "bar";
this.foobar = function () {
return this.foo;
}
}
var r = new Router();
r.foo // Accessible
Example with var :
function Router() {
var _foo = "bar";
this.foobar = function () {
return _foo;
}
}
var r = new Router();
r._foo // Not accessible