Scope private classes in a separate file - javascript

Is there a way to create a private class in a separate file without polluting the global namespace? Currently I just create a sub-namespace and put all of the private classes that other public classes need to function, but is there a way to just make a class altogether private, yet in another file?

You are probably looking for the "Module Pattern" in JavaScript. The Module Pattern name can refer to a lot of different patterns but the basic concept to to declare functions and attributes that are only available to a function which has already been called. Like this:
myModule = function () {
var me = {},
iAmPrivate = 1;
function privateFunc() {
// stuff can access iAmPrivate and iamPublic
}
me.iamPublic = 1;
me.publicFunc = function () {
// stuff can access iAmPrivate and iamPublic
};
return me;
}());
myModule.publicFunc(); // this can be called
myModule.iamPublic; // this can be accessed
myModule.iAmPrivate // xx can't do this
myModule.privateFunc() // or this
Because of how closures and scope works, Items declared local to that function call are available to all functions declared in that function call but nothing outside of the function call. The function has been called so they can never be accessed.
You can read a lot more about it here : http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html, and of course with a Google search now that you know what it is called.

Related

Closure factory exported from module does not give parent scope

Is it possible for a factory function imported from a module to return a closure that has access to the importing scope? Struggling to understand this in the world of closures and IIFEs. See below
module.js
function makeClosure() {
return function() {
//I want to access variables from any context where makeClosure is called here
//I always know variable names here
//eg:
console.log(someVar)
}
}
export default makeClosure
anotherModule's.js
import makeClosure from './module.js'
let someVar = 'hello!'
let closure = makeClosure()
closure() //print 'hello!'
I get a working closure if makeClosure is defined in the module where it is being used, but not if importing from another module. The application in this case is to put a set of functions that operate on the Google Maps API in a module so I can reuse them with different map instances in different parts of my app.

Scope issue inside objects that are inside objects

I've come across a problem while trying to build a simple jQuery plugin, having to do with scopes I guess.
The problem in short: A class (A) creates an object (B), in which a property (C) is set to one of the class methods (D). How can I access class A's methods not contained inside the object (B) through the property ( C)?
Longer version (code below): I'm declaring an object (lets call it publicMethods) inside the plugin, comprised of a bunch of methods. These methods should be some default methods (declared inside the plugin), or user declared ones if the user has declared her own when initializing the plugin.
The idea is that when the user defines her own custom method, there should be some functions and variables accessible to her (like this.someVar) in that function.
This creates some limitations though.
I want the default methods to have access to some internal functions and variables, not contained inside the object publicMethods. But when I access these methods through the object they are inside, instead of calling them directly, I do not have access to another variables/functions not inside that object.
I'm trying to find a way to let the default methods have access to it's class siblings. I know I can do some conditional statements before calling the method (if it is user defined or not), or even declare a global variable pointing to "this", but I'd rather keep it clean.
var Plugin = function (opt) {
this.settings = $.extend({
"someVar" : "Value",
"someFunc" : null
});
this.anotherVar = "Hello World";
this.setPublic();
this.run();
}
Plugin.prototype = {
setPublic: function() {
this.publicMethods.someFunc = this.someFunc;
if ($.isFunction(this.settings.someFunc)) {
this.publicMethods.someFunc = this.settings.someFunc;
} else {
this.publicMethods.someFunc = this.someFunc;
}
},
someFunc: function(arg) {
return this.anotherVar; // returns type error the second time
},
run: function () {
this.someFunc();
this.publicMethods.someFunc();
}
}
From MDN: Function.prototype.bind():
The bind() method creates a new function that, when called, has its this keyword set to the provided value, [...].
So the following should work:
setPublic: function() {
this.publicMethods.someFunc = this.someFunc.bind(this);
if ($.isFunction(this.settings.someFunc)) {
this.publicMethods.someFunc = this.settings.someFunc.bind(this);
}
// This is redundant anyway:
/* else {
this.publicMethods.someFunc = this.someFunc.bind(this);
}*/
},

Export objects vs functions NodeJs

Export Objects {} vs Export function
I'm developing an exercise application, I came across to the question When do I need to exports an object {} instead of a function class?
Scenario example:
I'm building a simple authentication module using the object style.
// file auth.js
module.exports = {
login: function() {
// code login
},
logout: function() {
// code logout
},
register: function() {
// code register
}
}
Here I'm using the anonymous function style
module.exports = function() {
return {
login: function() {
// code login
},
logout: function() {
// code logout
},
register: function() {
// code register
}
}
}
Requiring
When I want to require this module I just do:
var auth = require('auth');
auth.login(); // trigger login function via object
auth().login() // trigger login function via function
It will work with both the approaches, but I'm confused to choose which fit better and why.
Questions
How do you understand in your design of a module, when is appropriate to exports, an object, anonymous function, named function to Instantiate?
Which are the difference and how the require method behave, when requiring these functions or Objects ?
How do you understand in your design of a module, when is appropriate to exports, an object, anonymous function, named function to Instantiate?
true minimalists aim to export a single function if that will suffice. This is based on the scope of your module and assumes a small and focused purpose.
Export an object of related functions when you need a set of functions to have a meaningful set of functionality. For example, a tempConversion module might have both cToF and fToC functions.
If you are doing OO, exporting the constructor function is fine.
a closure function that returns the real payload (which can be an object or a function) is useful for configuration options. For example var tip = require('computeTip')(18); could store 18 in closure and return a function that would calculate 18% tip when called with a number.
Here's a rule of thumb: if you export only one named function a la require('average').average(listOfNumbers), it's redundant, so just export the average function directly to make it more concise. If you have more than one function you want to expose, use an object whose properties are the functions.
Which are the difference and how the require method behave, when requiring these functions or Objects ?
There are no differences. require has a single behavior that accommodates each of these techniques.
In both your examples you actually return an object and not a function class. In the second case you get the object by executing the function. In order to use the function as a class you should return a function which acts as the constructor, and then instantiate with the new operator.
That being said, I would prefer an object over a class if I consider my module as a singleton, something that would be common to every file that would include it. An example would be a module that implements a common access layer to my database.
A class makes more sense if you intent to instantiate it multiple times. An example would be a specific model class for your database schema, like a User class.

Issue related to declaring Variable in Famo.Us

I have Small application in Famo.us Framewok.
I want to declare array variable that can be use in calling js.
I have 2 .js file: (1) PageView.js (2) GetContent.js
(1) PageView.js
function AddContent() {
View.apply(this, arguments);
var getContent = new GetContent();
getContent.AddPages();
(2)GetContent.js
function GetContent() {
View.apply(this, arguments);
}
GetContent.prototype = Object.create(View.prototype);
GetContent.prototype.constructor = GetContent;
GetContent.DEFAULT_OPTIONS = {};
GetContent.prototype.AddPages = function () {
GetData();
}
I want to declare array variable in GetContent.js file that can be accessible in PageView.js using the object of GetContent defiened in PageView.js in above code.
so that i can use like getContent.variablename[1]
how to achieve it?
Your GetContent class would need to have an array assigned to it's instance like so:
this.variablename[1, 2, 3];
Adding this allows your array to be attached to the class's specific instance. Otherwise, your array will only exist for the lifetime of the function scope you create it in.
You may also find that you can't access the getContent object after it's been created in your PageView for the same reason. Instead try this.getContent = new GetContent();
Lastly, try to avoid directly accessing other class's variables directly. Instead, use getter/setter methods which allow the class to share and modify their data securely.

Using instance functions from constructor using WinJS

I have a function defined roughly as follows:
var myNamespace = WinJS.Namespace.define("MyNamespace", {
myClass: WinJS.Class.define(
function (myVariable) {
myFunction(myVariable);
},
{
myFunction: function FunctionMine(myVariable) {
// Do stuff
}
...
I'm using WinJS to write a windows store app, and the above format doesn't seem to work - it doesn't recognise myFunction as a function. Is it possible to reference an instance member of the class from the class constructor?
You need to use "this.myFunction".
Your function isn't in the scope to let you call it in that way.

Categories