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 ;
js files index.js and utils.js
I have tried to do the module export solution with no luck.
To call a function in utils.js from index.js I write a the function in utils as
export.functioname = function(parms) {
...
};
If i want to call the same function internally from utils.js i can do it i have to write another identical function as:
var functionname (parms) {
...
}
How can i get around this and only have one function to be called externally and internally?
You can use:
var yourfunction = function(param){
console.log(param);
}
exports.yourfunction = yourfunction;
yourfunction("Works");
Which prints:
"Works"
Functions can be saved to variables
var moo = function(parms) {};
export.functioname = moo;
or
function moo(parms) {};
export.functioname = moo;
works aswell because of js closures
I have a file stats.js.
It's contents are
(function () {
func1 = function () {
}
func2 = function () {
}
module.exports = this;
}).call(this);
Alegedly, when I do
var stats = require("./stats");
I should be able to get func1 and func2 with stats.func1, stats.func2, right?
Well, I can't. The stats object is just empty. A few traces in the stats.js revealed that "this" is also an empty object.
What gives?
First and foremost see this link.
Now lets see your code -
var stats = require("./stats");
//My steps -
//First Log
console.log(stats.func1); // returns undefined
//Second Log
console.log(global.func1, global === GLOBAL); // returns [Function], true
Take aways from this code -
1. In the browser the global object is window object.
2. In node.js it is the global object.
3. Defining something using var in a module will only create a variable with a module scope.
4. Defining something without the var keyword will create a variable in the global scope.
So func1 and func2 were defined in the global scope. Passing this to module.exports will pass the current module object only.
hope it helps, happy coding!
No it shouldnt? That format is nothing like what Node.js needs in order to do its job.
"What gives" is that you didn't read up on how node works. Node.js isn't just "JavaScript", it's a proramming model with a much richer API and specific behaviours. Requires use the "module.exports" object, so it would be a good idea to actually read up on how to use node.
mything.js:
var func3 = function() { ... },
prop = "something";
...
module.exports = {
func1: function() { ... },
func2: function() { ... },
func3: funct3,
prop: prop,
...
};
which is identical to:
var func3 = function() { ... },
prop = "something",
...
MyLib = {
func1: function() { ... },
func2: function() { ... },
func3: funct3,
prop: prop,
...
};
...
module.exports = MyLib;
app.js:
var mything = require("mything);
(function () {
pm.view.functionName= function () {
function nameFunction() {
var something;
return something;
}
return win;
};
})();
I am in another JS file and i want to call this nameFunction()... how can i do this. I tried...
pm.view.functionName().nameFunction()
But i get an error called, cannot call function in the Object. How can i access the functions from other JS files.
The function nameFunction exists in the scope of the function functionName. You cannot access it from outside that function.
If you want to do so, you'll have to explicitly say so:
pm.view.functionName.nameFunction = function() {
var something;
return something;
};
You could then access it as pm.view.functionName.nameFunction().
nameFunction is local to pm.view.functionName and you cannot access it, just like you cannot access local variables. You can call nameFunction() only when being inside pm.view.functionName.
Let's say I am writing code at the main page level and 2 dependencies require the same instance of an object and also state that as a dependency. What is the appropriate way to go about this?
Basically what I want to do is say, "If this dependency isn't loaded... then load it. Otherwise, use the same instance that was already loaded and just pass that one."
You would make that a module-level variable. For example,
// In foo.js
define(function () {
var theFoo = {};
return {
getTheFoo: function () { return theFoo; }
};
});
// In bar.js
define(["./foo"], function (foo) {
var theFoo = foo.getTheFoo(); // save in convenience variable
return {
setBarOnFoo: function () { theFoo.bar = "hello"; }
};
}
// In baz.js
define(["./foo"], function (foo) {
// Or use directly.
return {
setBazOnFoo: function () { foo.getTheFoo().baz = "goodbye"; }
};
}
// In any other file
define(["./foo", "./bar", "./baz"], function (foo, bar, baz) {
bar.setBarOnFoo();
baz.setBazOnFoo();
assert(foo.getTheFoo().bar === "hello");
assert(foo.getTheFoo().baz === "goodbye");
};
Just provide an API for your singleton as you would.
And make sure its lazily loaded. The easiest way is to use an abstraction library like underscore that supplies cross browser helpers. Other options are ES5 Object.defineProperty or custom getter/setters.
In this case _.once ensures that constructor's result is cached after the first call, it basically lazy loads it.
define(function() {
var constructor = _.once(function() {
...
});
return {
doStuffWithSingleton: function() {
constructor().doStuff();
}
};
});
_.once from underscore.
Combining Raynos's concerns about encapsulation with the OP's clarification that he wants to expose a couple of methods on a messaging service, this is I think the right way to go about it:
// In messagingServiceSingleton.js
define(function () {
var messagingService = new MessagingService();
return {
notify: messagingService.listen.bind(messagingService),
listen: messagingService.notify.bind(messagingService)
};
});
// In bar.js
define(["./messagingServiceSingleton"], function (messagingServiceSingleton) {
messagingServiceSingleton.listen(/* whatever */);
}
// In baz.js
define(["./messagingServiceSingleton"], function (messagingServiceSingleton) {
messagingServiceSingleton.notify(/* whatever */);
}
Function.prototype.bind will not be present in all browsers, so you would need to include a polyfill like the one Mozilla provides.
An alternate (and in my opinion probably better) approach would be to make the messaging service object itself a module. This would look something like
// In messagingService.js
define(function () {
var listenerMap = {};
function listen(/* params */) {
// Modify listenerMap as appropriate according to params.
}
function notify(/* params */) {
// Use listenerMap as appropriate according to params.
}
return {
notify: notify
listen: listen
};
});
Since you expose the same notify and listen methods to everyone who uses your module, and those always refer to the same private listenerMap variable, this should do what you want. It also obviates the need for Function.prototype.bind, and gets rid of the rather-unnecessary distinction between the messaging service itself and the module which enforces singleton usage of it.
Here's a version where the module itself is the shared variable instead of a variable within that module.
define('foo', [], {bar: "this text will be overwritten"});
define('bar', ["foo"], function (foo) {
return {
setBarOnFoo: function () { foo.bar = "hello"; }
};
});
define('baz', ["foo"], function (foo) {
return {
setBazOnFoo: function () { foo.baz = "goodbye"; }
};
});
require(["foo", "bar", "baz"], function (foo, bar, baz) {
bar.setBarOnFoo();
baz.setBazOnFoo();
$('#results').append(foo.bar + ' ' + foo.baz);
});
// reads: hello goodbye
As a variation of Domenic's answer, you can use the 'exports' magic module to automatically generate a reference for the module -- "Properties added to the exports object will be on the public interface of the module, no need to return any value." This avoids having to call the getTheFoo() function to obtain a reference.
// In foo.js
define(['exports'], function (foo) {
foo.thereCanBeOnlyOne = true;
});
// In bar.js
define(["exports", "./foo"], function (bar, foo) {
bar.setBarOnFoo = function () { foo.bar = "hello"; };
});
// in baz.js
define(["exports", "./foo"], function (baz, foo) {
baz.setBazOnFoo = function () { foo.baz = "goodbye"; };
});
// In any other file
define(["./foo", "./bar", "./baz"], function (foo, bar, baz) {
bar.setBarOnFoo();
baz.setBazOnFoo();
assert(foo.bar === "hello");
assert(foo.baz === "goodbye");
assert(foo.thereCanBeOnlyeOne);
});
To address the comment below, I personally have found the above convention to be useful. Your mileage may vary, but feel free to adopt the convention if you think it is useful. The convention boils down to these two rules:
Declare 'exports' as the first dependency in the define array.
Name the parameter in the function after the JavaScript file.
Using the name of file, e.g. for foo.js name the variable 'foo', increases the readability of the code as most developers will define 'foo' as the parameter for the foo.js dependency. When scanning the code or using grep, it is easy to find all references to 'foo' use both inside and outside the module and it makes it easy to pick out what the module is exposing to the public. For example, renaming bar.setBarOnFoo to bar.setFooBar is much easier if the declaration in the bar.js module mirrors the usage in other files. A simple search and replace of bar.setBarOnFoo to bar.setFooBar across all files will accomplish the task.
I was in this scenario:
For different reasons I needed to call a function that was on a requirejs module, but the click that fired that call was out of require.
The way I fixed this was creating a requirejs modure that writes over the window object.
define("one", [], function() {
window.popupManager = (function () {
console.log ('aca');
var popUpManager = function () {
self = this;
self.CallMe = function ()
{
alert ('someone calls');
};
};
return new popUpManager();
})();
});
require(['one']);
window.popupManager.CallMe();
This way if any piece of code that is out of the require spectrum (I know it shouldn't be this way) can call functions of this require that writes over the window object.
I really know this is not an "elegant" solution, but it may help you in case of an emergency.