I was searching over the Internet for good JS practices and found an interesting one (that sadly, I don't understand it entirely)
myNameSpace = function(){
var current = null;
function init(){...}
function change(){...}
function verify(){...}
return{
init:init,
change:change
}
}();
Where can I use this name space?
How can I use the names pace?
Is it really good idea to use this instead of Global?
Source of script: http://dev.opera.com/articles/view/javascript-best-practices/
You can also use a code like this, that lets you write OO JavaScript code. You should group only cohesive functions in one unit and build more objects like this as needed.
Note that function buildFullName is a private function, since it can't be accessed from outside.
I agree with you that is confusing, without previous JavaScript knowledge. The fact is that a function is a first class Object in JavaScript. You can nest functions within functions, they can have variables, and there are so many ways to combine them, there is no standard way like in Java. I think the article JavaScript Closure 101 can help you clear things up a bit.
/** This is our Object definition and constructor */
function Person(fname, lname) {
this.firstName = fname;
this.lastName = lname;
}
/** Anonymous function to avoid polluting the global namespace */
(function () {
/** This function will be defined public, we prefix the class name */
function Person_toString() {
//call buildFullName passing this, we could also call the function
//as buildFullName(), and it would work, but wouldn't have 'this'
return buildFullName.call(this);
}
/** Another public function */
function Person_buildGreeting() {
return "Hi " + this.firstName;
}
/** This function is private! */
function buildFullName() {
return this.firstName + " " + this.lastName;
}
/** Here we augment the Object with public functions */
Person.prototype = {
toString: Person_toString,
buildGreeting: Person_buildGreeting
};
})(); //execute the anonymous function immediately
Example usage:
var p1 = new Person('Jenny', 'Fairview');
alert("toString()=" + p1.toString());
alert("buildGreeting()=" + p1.buildGreeting());
That was one poor article, at least the section on avoiding globals. These things arise when your code gets so incredibly large that eventually you will come to give it a prefix, for example dojo. All/Most dojo functions start with dojo. so when you load it, it doesn't overwrite your functions (of course this assumes you don't have a function or variable called dojo).
If you have 1000 functions in the form
function init(){...}
function run(){...}
function start(){...}
The argument they're making is that it's easier to do
packageName = function{
function init(){...}
function run(){...}
function start(){...}
return {
init : init ,
run : run ,
start : start
}
than
packageName = function{
init : function init(){...} ,
run : function run(){...} ,
start : function start(){...}
}
I prefer the latter. It's cleaner, more concise, and less confusing.
You can go a little further and use CommonJS or AMD modules to construct your application and avoid globals pretty much altogether. Dojo is moving in this direction, but has not yet migrated away from using dojo.*
Related
Background
I've been working with OOP style Javascript for the past few months, starting with just dissecting open source libraries. It seems like they mostly follow the same pattern, except that I've seen two ways of handling private functions, and I'm wondering which is the best (best as in best practice, or better for reasons I might not know about).
Example Code
Below is a very stripped down skeleton of the pattern I'm using. If you'll note, there are two different forms of private functions.
The first is attached to the prototype like public functions, but is prefixed with an _.
The second is just a function who's scope is only accessible by the class.
(function(window) {
window.FooBarClass = (function() {
var Class = function( params ) {
this._init( params );
}
/***************************************/
/************* INITIALIZE **************/
/***************************************/
Class.prototype._init = function( params ) {
// DO SETUP STUFF
};
/***************************************/
/********** PUBLIC FUNCTIONS ***********/
/***************************************/
Class.prototype.doThings = function() {
// DO STUFF
};
/***************************************/
/****** PRIVATE FUNCTIONS 1ST WAY ******/
/***************************************/
Class.prototype._createSection = function( params ) {
// DO STUFF
};
/***************************************/
/****** PRIVATE FUNCTIONS 2ND WAY ******/
/***************************************/
function correctTwoDigitYear( variable ) {
// DO STUFF
}
return Class;
}());
}(window));
Question
Which of these is preferable, and why?
JS doesn't actually have private methods, though as you've seen you can limit access to functions and variables by closing over their scope.
In the end, if it's on the prototype, it's not private--regardless of naming convention (leading underscores, etc). So if you really want to limit access to something, do NOT put it on the prototype.
The second pattern, putting functions in the local scope, is preferable because it's actually private. It's not really OOP though.
The first pattern, putting functions in underscored properties on the prototype, is preferable because they are actual methods that get their this passed implicitly like you expect of a method. By being instance methods, they are available to any module that needs them, instead of being restricted by scope, which can be beneficial in larger projects. And of course methods are important in OOP as they offer dynamic dispatch if you want to use polymorphism.
Also prototype methods are (were?) a bit better optimised, so they were chosen if you need to squeeze out the last bit of performance, though in practice you won't see much difference to a plain function call.
any method that is attached to the prototype property of a function is accessible by the object or by the child class. SO,
class.prototype.__init
cannot be considered as a private method.
It can be accesible by the object or it can be modified by extending the class
ex:
var someClass = (function () {
var Class = function( params ) {
this._init( params );
}
Class.prototype._init = function( params ) {
console.log("Hello World");
};
return Class;
} ());
var extendSomeClass = someClass;
extendSomeClass.prototype._init = function () {
console.log("Hey there");
}
var obj = new extendSomeClass(); // this wil print "Hey there"
In the example that you have posted, the _init is acting as a constructor, hence the property associated with it is made public (though the naming convention suggests a private member). But to follow a private access, a closure scope should be the best practice.
example:
var fooClass = (function () {
var Class = function () {
if(this._init) {
this._init.apply(this, arguments);
}
}
Class.prototype.hello = function () {
log("hello world");
}
function log(args) {
console.log(args);
}
}());
In the example above the function log is a private method and cannot be modified/overridden outside the scope.
I'm pretty new to javascript and I read about the module pattern to provide some sort of namespace and have both private and public members, for example:
var module = (function() {
var s = "Hello, i'm private and in closure!";
return {
myString : s,
myFunc: function() { alert(s); }
};
})();
I do see the benefits of that, because it gives you some of the advantages of object-oriented programming. But I've seen a lot of examples of an IIFE that doesn't get assigned to a variable. This (as far as I see) has no advantages at all compared to a normal function that you invoke:
1. IIFE
(function() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
})();
2. Normal function
function Initialize() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
}
Initialize();
They both have private variables that avoid the need of creating global variables and they both execute without returning any value to a variable.
Although the second one gives you the option of choosing a good name that says a lot more than a potential large IIFE without the name, leaving the reader to find out what's happening. The answer I see everywhere is 'to avoid namespace pollution' but both approaches do that, the first one is just a bit harder to understand?
In short:
What is the benefit of using an IIFE over a normal function that I'm missing? Why should I use them?
Sometimes you need to define and call function at the same time and only once so in this case anonymous function helps you. In such situations giving functions a name and then calling them is just excess.
Further sometimes you wants to create a namespace for your variables. So anonymous functions helps you there too. For example
(function($) {
$.fn.pluginName = function(opt) {
// implementation goes here...
}
}(jQuery));
In above case you can safely use $ as jQuery synonym in your code.
If you define a function with name as shown below, then it will create global variable with function name as you defined.
function myFunction() {
// function code goes here.
}
myFunction();
But if you define it without name then it won't create any global variable and your global namespace will not be polluted.
(function myFunction() {
// function code goes here.
}());
Function with names are useful only when you need to call them from different places in your code.
In Ruby I think you can call a method that hasn't been defined and yet capture the name of the method called and do processing of this method at runtime.
Can Javascript do the same kind of thing ?
method_missing does not fit well with JavaScript for the same reason it does not exist in Python: in both languages, methods are just attributes that happen to be functions; and objects often have public attributes that are not callable. Contrast with Ruby, where the public interface of an object is 100% methods.
What is needed in JavaScript is a hook to catch access to missing attributes, whether they are methods or not. Python has it: see the __getattr__ special method.
The __noSuchMethod__ proposal by Mozilla introduced yet another inconsistency in a language riddled with them.
The way forward for JavaScript is the Proxy mechanism (also in ECMAscript Harmony), which is closer to the Python protocol for customizing attribute access than to Ruby's method_missing.
The ruby feature that you are explaining is called "method_missing" http://rubylearning.com/satishtalim/ruby_method_missing.htm.
It's a brand new feature that is present only in some browsers like Firefox (in the spider monkey Javascript engine). In SpiderMonkey it's called "__noSuchMethod__" https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/NoSuchMethod
Please read this article from Yehuda Katz http://yehudakatz.com/2008/08/18/method_missing-in-javascript/ for more details about the upcoming implementation.
Not at the moment, no. There is a proposal for ECMAScript Harmony, called proxies, which implements a similar (actually, much more powerful) feature, but ECMAScript Harmony isn't out yet and probably won't be for a couple of years.
You can use the Proxy class.
var myObj = {
someAttr: 'foo'
};
var p = new Proxy(myObj, {
get: function (target, methodOrAttributeName) {
// target is the first argument passed into new Proxy, aka. target is myObj
// First give the target a chance to handle it
if (Object.keys(target).indexOf(methodOrAttributeName) !== -1) {
return target[methodOrAttributeName];
}
// If the target did not have the method/attribute return whatever we want
// Explicitly handle certain cases
if (methodOrAttributeName === 'specialPants') {
return 'trousers';
}
// return our generic method_missing function
return function () {
// Use the special "arguments" object to access a variable number arguments
return 'For show, myObj.someAttr="' + target.someAttr + '" and "'
+ methodOrAttributeName + '" called with: ['
+ Array.prototype.slice.call(arguments).join(',') + ']';
}
}
});
console.log(p.specialPants);
// outputs: trousers
console.log(p.unknownMethod('hi', 'bye', 'ok'));
// outputs:
// For show, myObj.someAttr="foo" and "unknownMethod" called with: [hi,bye,ok]
About
You would use p in place of myObj.
You should be careful with get because it intercepts all attribute requests of p. So, p.specialPants() would result in an error because specialPants returns a string and not a function.
What's really going on with unknownMethod is equivalent to the following:
var unk = p.unkownMethod;
unk('hi', 'bye', 'ok');
This works because functions are objects in javascript.
Bonus
If you know the number of arguments you expect, you can declare them as normal in the returned function.
eg:
...
get: function (target, name) {
return function(expectedArg1, expectedArg2) {
...
I've created a library for javascript that let you use method_missing in javascript: https://github.com/ramadis/unmiss
It uses ES6 Proxies to work. Here is an example using ES6 Class inheritance. However you can also use decorators to achieve the same results.
import { MethodMissingClass } from 'unmiss'
class Example extends MethodMissingClass {
methodMissing(name, ...args) {
console.log(`Method ${name} was called with arguments: ${args.join(' ')}`);
}
}
const instance = new Example;
instance.what('is', 'this');
> Method what was called with arguments: is this
No, there is no metaprogramming capability in javascript directly analogous to ruby's method_missing hook. The interpreter simply raises an Error which the calling code can catch but cannot be detected by the object being accessed. There are some answers here about defining functions at run time, but that's not the same thing. You can do lots of metaprogramming, changing specific instances of objects, defining functions, doing functional things like memoizing and decorators. But there's no dynamic metaprogramming of missing functions as there is in ruby or python.
I came to this question because I was looking for a way to fall through to another object if the method wasn't present on the first object. It's not quite as flexible as what your asking - for instance if a method is missing from both then it will fail.
I was thinking of doing this for a little library I've got that helps configure extjs objects in a way that also makes them more testable. I had seperate calls to actually get hold of the objects for interaction and thought this might be a nice way of sticking those calls together by effectively returning an augmented type
I can think of two ways of doing this:
Prototypes
You can do this using prototypes - as stuff falls through to the prototype if it isn't on the actual object. It seems like this wouldn't work if the set of functions you want drop through to use the this keyword - obviously your object wont know or care about stuff that the other one knows about.
If its all your own code and you aren't using this and constructors ... which is a good idea for lots of reasons then you can do it like this:
var makeHorse = function () {
var neigh = "neigh";
return {
doTheNoise: function () {
return neigh + " is all im saying"
},
setNeigh: function (newNoise) {
neigh = newNoise;
}
}
};
var createSomething = function (fallThrough) {
var constructor = function () {};
constructor.prototype = fallThrough;
var instance = new constructor();
instance.someMethod = function () {
console.log("aaaaa");
};
instance.callTheOther = function () {
var theNoise = instance.doTheNoise();
console.log(theNoise);
};
return instance;
};
var firstHorse = makeHorse();
var secondHorse = makeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
This doesn't work for my use case as the extjs guys have not only mistakenly used 'this' they've also built a whole crazy classical inheritance type system on the principal of using prototypes and 'this'.
This is actually the first time I've used prototypes/constructors and I was slightly baffled that you can't just set the prototype - you also have to use a constructor. There is a magic field in objects (at least in firefox) call __proto which is basically the real prototype. it seems the actual prototype field is only used at construction time... how confusing!
Copying methods
This method is probably more expensive but seems more elegant to me and will also work on code that is using this (eg so you can use it to wrap library objects). It will also work on stuff written using the functional/closure style aswell - I've just illustrated it with this/constructors to show it works with stuff like that.
Here's the mods:
//this is now a constructor
var MakeHorse = function () {
this.neigh = "neigh";
};
MakeHorse.prototype.doTheNoise = function () {
return this.neigh + " is all im saying"
};
MakeHorse.prototype.setNeigh = function (newNoise) {
this.neigh = newNoise;
};
var createSomething = function (fallThrough) {
var instance = {
someMethod : function () {
console.log("aaaaa");
},
callTheOther : function () {
//note this has had to change to directly call the fallThrough object
var theNoise = fallThrough.doTheNoise();
console.log(theNoise);
}
};
//copy stuff over but not if it already exists
for (var propertyName in fallThrough)
if (!instance.hasOwnProperty(propertyName))
instance[propertyName] = fallThrough[propertyName];
return instance;
};
var firstHorse = new MakeHorse();
var secondHorse = new MakeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
I was actually anticipating having to use bind in there somewhere but it appears not to be necessary.
Not to my knowledge, but you can simulate it by initializing the function to null at first and then replacing the implementation later.
var foo = null;
var bar = function() { alert(foo()); } // Appear to use foo before definition
// ...
foo = function() { return "ABC"; } /* Define the function */
bar(); /* Alert box pops up with "ABC" */
This trick is similar to a C# trick for implementing recursive lambdas, as described here.
The only downside is that if you do use foo before it's defined, you'll get an error for trying to call null as though it were a function, rather than a more descriptive error message. But you would expect to get some error message for using a function before it's defined.
Let's start from the code:
function say(name) {
var ghost=function () {
function ghost() {
alert('!');
};
return body;
};
eval("var body=''+"+name+';');
eval(name+('=('+ghost).replace('body', body)+')();');
eval(name+'();');
}
function Baal() {
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
say('Baal'); // or just Baal();
Looks like that saying the devil's name invoke his presence (well, maybe he needs somebody for spiritual possession) ..
As you can see the ghost doesn't exist along with Baal, but we can invoke it since there're evals in say(name).
say(name) reassigns Baal to its code body as a closure and makes it captured a ghost method, that's how things work. But I'm trying to avoid eval ..
So .. let me reword the question:
How do I make a nonexistent(and not a member or global) method invocable without using eval?
Let me rephrase your question, just to make sure I’ve got it. Given a function, you want to put a new variable in its scope, without that scope being the global scope or a scope shared between the caller and the subject, without using eval (or the equivalent new Function and other hacks depending on the environment).
You can’t.
In the case you just mentioned, you could define one function, base(), that uses arguments.callee.caller.
Don’t do that.
The short answer: You don't.
That scope is not available. If you were to attach the scope then it would be available inside of the scope used. You could then access the method handles. I assume this is not what you were looking for, but here is what that would look like. demo
function say(name){
var methods = {};
methods.Baal = function(){
alert("!");
};
return methods[name];//this could invoke as well: methods[name]()
}
var handle = say('Baal');
handle();
What your evals break down to is something along these lines (although with dynamic content from string building - this is the end result)
function say(name) {
var Baal = (function () {
function ghost() {
alert('!');
};
return function(){
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
})();
Baal();
}
say('Baal'); // or just Baal();
Note that the meat of what happens here is from the function Baal, namely that it calls a hardcoded ghost() which in turn calls a hardcoded alert. Why go through all of this trouble to access a hardcoded function?
A better way would be to inject this function as a callback which expects some parameters to be injected.
jsFiddle Demo
function say(callback){
var params = "!";
if( typeof callback == "function" ){
callback(params);
}
}
say(function(params){
alert(params);
});
It's very difficult for me to read through your code and figure out what you are trying to accomplish with it, but it appears that you are trying to introduce a variable into the current scope so that you can call it. You cannot do this in javascript with the method that you demonstrated. Scoping only ever "flows down". By that I mean that a variable or function defined within a function will only be available to that function and any other functions defined therein. Your function named ghost will only ever be available within the function where it is defined, regardless of when that function is evaluated.
What you can do, however, is write a function that returns a function. You can then call that function and assign the result to a variable in the scope where you want to expose functionality. Doing that would look something like this.
function defineSpecialAlert() {
return function(name) {
alert(name + "!");
};
}
var newlyDefinedMethod = defineSpecialAlert();
newlyDefinedMethod("Baal");
So if I understand, it seems like you want to create an alias of eval: Something like
#Note this code is not intended as a solution, but demonstrates
#an attempt that is guaranteed to fail.
#
function myAlias(ctx) {
eval.call(ctx, 'var ghost = 42');
}
myAlias(this);
alert(ghost);
Javascript allows many funky sleight-of-hand tricks especially with closures, but this is maybe the one impossible thing that javascript cannot do. I've tried at length to do this exact same thing, and I can tell you that you'll run into nothing but complaints from the browser, saying that eval cannot be re-contexted or aliased in any way.
I've got the first file in my code directory as follows
myNamespace.js
var myNamespace = {};
Then my subsequent files can look as one of the two following ways.
first
(function (ns) {
ns.DoStuff = function(){
// do stuff
}
})(myNamespace);
second
myNamespace.DoStuff = function(){
//do stuff
}
So what is the difference between these two methods? Both seem to work for me. Is there a more generally accepted convention?
sorry, still new to javascript
Your first approach will not work. It would create DoStuff on the global object (most likely window). You would need to replace this with ns, after you did that, there is no difference between the two approaches.
The former will have the adventage that you might be able to closure all your application/file related stuff into that outer self-invoking closure function. So you won't clobber the global namespace.
(function (ns) {
var foo = 10,
bar = 42;
ns.DoStuff = function(){
console.log('foo is ', foo, ' and its not available globally');
}
})(myNamespace);
You have an error in your first one, you've used this where I'm pretty sure you meant ns:
ns.DoStuff = function() {
};
Leaving that aside, your first approach tends to be better because you've created a nice little scoping function for yourself, which allows you to have private data and functions available to all of the public methods you create on your namespace, without making them globals. E.g.:
(function(ns) {
function privateFunction() {
}
ns.DoStuff = function() {
privateFunction(); // <=== works fine
};
})(myNamespace);]
privateFunction(); // <=== doesn't work, because it's private
I like doing it that way partially because I have thing against anonymous functions, and so I wouldn't define DoStuff as above, but rather like this:
(function(ns) {
ns.DoStuff = Namespace$DoStuff;
function Namespace$DoStuff() {
}
})(myNamespace);
Now the function I've assigned to myNamespace.DoStuff has a proper name, which helps me out when I'm debugging my code. But that name doesn't pollute the global namespace, which helps me stay sane and avoid conflicts with other code.