I've just seen this pattern in javascript:
var test = function () {
function test(args) {
this.properties = args || {}; //etc
}
}
test.prototype.methodName = function (){} //...etc
What is going on with the function definition; declared once outside and once inside. What is the value of this approach?
It is strange. The "outer" function acts as a constructor, you can use var myTest = new test(); to create a new test.
The inner function, because of JS function-scoping, would only be available within the constructor method. You could call the inner test(...) from within the constructor, but it seems pointless as presumably args should be passed in to the constructor.
What might have been intended is:
var test = function(args) {
this.properties = args || {}; // you may want to actually parse each arg here
}
test.prototype.someOtherMethod = function() {}
The first thing to understand here is that functions in JavaScript create new scopes – there is no block scope (yet). So every variable or function declared inside another function is not visible to the outside.
With that in mind: when you define the inner function with the same name of the outer, you lose the ability to call the outer function recursively from itself, by name, because the inner function will "take over" (or "shadow") that name. Inside both functions, test will refer to the inner function, and outside the outer function test always refer to the outer function.
Since after the function definition you're modifying test.prototype, we can assume test (the outer one) will be used as a constructor. In this case, the inner test can be seen as a "private" method of the constructor, callable only from within the constructor. For detailed examples of this object-oriented use of functions within functions, see James T's answer.
This is scope.
When you define a variable as a function, it creates function scope.
Inside that function you can declare the same name, because that function is declared within that scope... Take an easier to follow example:
var User = function()
{
function PrivateToScope()
{
// A Function Only Accessible Inside This Function
alert( "private" );
}
return
{
PublicToScope: function()
{
// A Function Accessible From Outside This Function
alert( "public" );
}
}
}
var James = new User();
James.PublicToScope(); // Will alert "public"
James.PrivateToScope(); // Will fail to do anything
So to explain the answer, the User sets scope, and because you declare the function as above wit the same name, it does not matter.
People do not like me saying this but you can think of this approach as if it were a class in other languages.
var User = function()
{
}
is like
class User
{
}
var User = function()
{
function Something()
{
}
}
is like
class User
{
private function Something()
{
}
}
and finally
var User = function()
{
this.Something = function()
{
}
// or
return {
Something: function(){}
}
}
is like
class User
{
public function Something()
{
}
}
It's alllll about scope. maybe you have a user variable declared as a function and you wish to allow people to get his first name and last name, you would declare these variables or functions as "public"... but what if you wanted to know his diet was good or bad, you may have some complex functions to work it out, but you want to know one thing, good or bad.. you could make all these functions that do ugly stuff private, and then just display the result with a public function...
var User = function()
{
function CalculateDiet()
{
// Lots of scary diet calculating stuff comes out with the result
return result;
}
return
{
FirstName: "James",
LastName: "Poop",
StandardOfDiet: function()
{
return CalculateDiet();
}
}
}
var MyUser = new User();
alert( MyUser.FirstName );
alert( MyUser.StandardOfDiet() );
Why do you care?
Quantifying it is both easy and hard but here are some good ones...
It's neat
If you place a pile of chocolates on a table, they'll all get eaten.. but one of them was for you, people are greedy... Only layout on the table what you want them to eat, they can't be greedy then an accidently eat your chocolate
It sets you up for class oriented programming
It's clear what the programmer meant to do with the code
Memory usage (I'm sure there are overheads to declaring more functions public without need to
Finally, and on a very different note, you have a prototype attached to test, so let's go do this for our user example. Imagine we had an array of users:
var users = [
new User(),
new User()
];
we can iterate over these and get all their usual properties and methods:
for( a in users )
{
alert( users[ a ].FirstName );
}
But let's say something happens in our application... a user clicks on a button that asks each user if they like fish and chips or not, we now need a new method for the user... We can prototype a new method to all iterations of that variable "user" we created... We could declare it before hand, but then we'd waste memory and maybe confuse future programmers with its presence that is based off of something very specific:
// user clicks button and runs this code
User.protoype.DoesUserLikeChips = function(){
// put some code in here that somehow makes this example make sense :)
}
now on every user in your array, you can call this new method... New functionality babehhh!
You may be thinking, why do you not just go users[ a ].DoesUserLikeChips = function(){}... The answer is that it is applied to only that one instance...
Inner test function is a private function of outer test function. And then a methodName function has been set as public function of outer test function. There are no special thing about naming inner function as outer one.
Related
Can nodejs have two functions in different classes with the same name ?
If not then why not ? otherwise there is something wrong in the code.
Following is the example;
var admins = require('./routes/admins');
var users = require('./routes/users');
Both singleton classes
var users = function users(){
this.foo = foo = function(bar){ ...
}
}
users.getInstance = getInstance = function(){
if(this.instance == null){
this.instance = new users();
}
return this.instance;
}
module.exports = users.getInstance();
The admin class is also similar, both the classes have the same function names as well.
Now when foo is called it gets called of user class no matter what.
If i change the require order the foo of admin class is called.
As literally written in your question, I don't see a reason why this would happen. However, you are leaking into global scope, and that's how you might end up with duplicates.
users.getInstance = getInstance = function(){ ...
First, notice that the middle getInstance isn't scoped with var, so it gets assigned to the global scope. While this doesn't cause immediate problems, you're still polluting global scope, which is bad.
The real issue appears if you just do:
module.exports = getInstance();
Whether or not you've scoped getInstance with var, you're calling it in the global context, which means that inside the function, this == global. This means that the first time the function runs, it is basically doing:
global.instance = new users();
...and when your second file runs, it sees there's already a global.instance and just returns it.
Consider using 'use strict'; so these kinds of errors are caught for you.
Finally -- why are you doing all these getInstance gymnastics? They are entirely unnecessary. Your users file should just look like:
exports.foo = function(bar) {
...
};
Since the function name are same and the code is executed in sequential order, the function inside the second class overrides the first.
So the function will be called from whichever file is in second place.
In traditional OOP language, we usually use private/public to implement data encapsulation.
In Javascript, there is no private or public anymore; someone told me; by using closure, the data encapsulation can be implemented. I am wondering how and what's the behind logic?
You can encapsulate data in a 'Class' (no real class before JavaScript 6) this way
var yourClass = function() {
var privateProp = 'sometext'; //private prop
this.prop = 1; //public
this.getPrivateProp = function() {
return privateProp; //access to your private prop with a closure
}
}
var test = new yourClass();
//when you use 'new', everything in 'this' is returned in your object.
//'privateProp' is not in 'this' but 'getPrivateProp' is.
//You got your private data not directly accessible from outside.
test.prop; // 1
test.privateProp;//undefined
test.getPrivateProp();// 'sometext'
Actually isn't creating actual private members.
Check the following code:
function A() {
var doStuff1 = function() { };
this.doStuff2 = function() {
doStuff1();
};
};
var instance = new A();
instance.doStuff2();
Since doStuff2 is declared and added to this, it's part of A instance while doStuff1 is declared as a local variable within the constructor function, and thus, it's only accessible using closures within the same constructor.
BTW I don't like this pattern since it works great when you don't use prototypal inheritance.
Let's say I want to use prototypes:
function A() {
var doStuff1 = function() {}; // ??????
};
A.prototype = {
doStuff2: function() {
// How do I access a local variable defined
// in the constructor function local scope?
}
};
So, the whole pattern works in simple scenarios where you don't want to use prototypal inheritance.
Also, this pattern won't work in scenarios where you want to use Object.create(...), since there's no constructor function at all...
// Constructor isn't ever called...
var instance = Object.create(A.prototype);
So, how you would implement this kind of encapsulation in JavaScript? For now isn't possible, but many libraries and frameworks have opted-in to use naming conventions to let developers know what's consumed by the library/framework code and what's intended for use in actual third-party developments.
For example:
function A() {
};
A.prototype = {
___doStuff1___: function() {},
doStuff2: function() {
this.___doStuff1___();
}
};
After all, this is a naming convention, where members which are sorrounded by ___ are considered private or not intended for third-party developers.
Other libraries/framework use $$ (f.e. Angular, $$privateMember).
I failed to create a mini-library with some useful functions that I have found over the Internet, and I want to use them easily by just including a file to the HTML (like jQuery).
The problem is that some vars and functions share the same name and they are causing problems.
Is there a better solution to this instead of giving crazy names to the vars/funcs like "bbbb123" so the odds that someone is working with a "bbbb123" var is really low?
I would put all of your functions and variables into a single object for your library.
var MyLibrary = {
myFunc: function() {
//do stuff
},
myVar: "Foo"
}
There are a few different ways of defining 'classes' in JavaScript. Here is a nice page with 3 of them.
You should take one variable name in the global namespace that there are low odds of being used, and put everything else underneath it (in its own namespace).
For example, if I wanted to call my library AzureLib:
AzureLib = {
SortSomething: function(arr) {
// do some sorting
},
DoSomethingCool: function(item) {
// do something cool
}
};
// usage (in another JavaScript file or in an HTML <script> tag):
AzureLib.SortSomething(myArray);
Yes, you can create an object as a namespace. There are several ways to do this, syntax-wise, but the end result is approximately the same. Your object name should be the thing that no one else will have used.
var MyLibrary = {
myFunc: function() { /* stuff */ }
};
Just remember, it's object literal syntax, so you use label : value to put things inside it, and not var label = value;.
If you need to declare things first, use a wrapping function to enclose the environment and protect you from the global scope:
var MyLibrary = (function() {
var foo = 'bar';
return {
myFunc: function() { /* stuff */ }
};
})(); // execute this function right away to return your library object
You could put all of your library's functions inside of a single object. That way, as long as that object's name doesn't conflict, you will be good. Something like:
var yourLib = {};
yourLib.usefulFunction1 = function(){
..
};
yourLib.usefulFunction2 = function(){
..
};
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
This is a very old problem, but I cannot seem to get my head around the other solutions presented here.
I have an object
function ObjA() {
var a = 1;
this.methodA = function() {
alert(a);
}
}
which is instantiated like
var myObjA = new ObjA();
Later on, I assign my methodA as a handler function in an external Javascript Framework, which invokes it using the apply(...) method.
When the external framework executes my methodA, this belongs to the framework function invoking my method.
Since I cannot change how my method is called, how do I regain access to the private variable a?
My research tells me, that closures might be what I'm looking for.
You already have a closure. When methodA is called the access to a will work fine.
Object properties are a different thing to scopes. You're using scopes to implement something that behaves a bit like ‘private members’ in other languages, but a is a local variable in the parent scope, and not a member of myObjA (private or otherwise). Having a function like methodA retain access to the variables in its parent scope is what a ‘closure’ means.
Which scopes you can access is fixed: you can always access variables in your parent scopes however you're called back, and you can't call a function with different scopes to those it had when it was defined.
Since a is not a property of this, it doesn't matter that this is not preserved when calling you back. If you do need to get the correct this then yes, you will need some more work, either using another closure over myObjA itself:
onclick= function() { myObjA.methodA(); };
or using Function#bind:
onclick= myObjA.methodA.bind(myObjA);
yes, you're right. Instead of a method reference
var myObjA = new ObjA();
libraryCallback = myObjA.methodA
pass a closure
libraryCallback = function() { myObjA.methodA() }
If you are using jQuery javascript framework, easiest way is to use proxy:
$('a').click($.proxy(myObjA, 'methodA'));
I'd do this:
function ObjA() {
this.a = 1;
this.methodA = function() {
alert(this.a);
}
}
function bindMethod(f, o) {
return function(){
return f.apply(o, arguments);
}
}
var myObjA = new ObjA();
myObjA.methodA = bindMethod(myObjA.methodA, myObjA);
...
Where bindMethod binds the methodA method to always be a method of myObjA while still passing on any arguments which function() {myObjA.methodA()} doesn't do.