I am a newbies to Javascript and recent need to support for it. May anyone help me to understand the following coding?
var proj = proj || {};
(function () {
var functA = function () {
var base = {}; // I don't understand from this line
base.getString = this.getString;
this.getString = function () {
var strings = base.getString.call($this);
return strings.concat(["ab","cd","ef"]);
};
};
})();
I am quite confused with the getString function. Can anyone kindly explain the purpose of it? Also, is there any name for such kind of coding style or can anyone lead me to some articles about this style of coding?
Many thanks.
In Javascript, curly braces define both scope (as in method definitions) and object types (what Ruby people call hashes and Python people call dictionaries). The line you're confused about is declaring a variable to be an empty object.
After that, the programmer is adding a function to their new object. Javascript throws references around like crazy, so the programmer has set up base.getStrings as an alias pointing to the getStrings function they define later.
As for the purpose of the function itself, my best guess is that it's generating test data, but without understanding the entire code base it's impossible to say,
The line var strings = base.getStrings.call($this) seems to be seeding the method with strings from another scope. I can't know what $this refers to, but intuition tells me that it is a reference to the this of an outer scope, which also has a getStrings method.
The call() method executes the function and forces resolution of the this keyword to the first parameter, in this case $this. Since base.getStrings is aliased to this.getStrings, the programmer can use this trick to force the call to $this.getStrings, avoiding an infinite recursion.
This looks like a super-call in a mixin pattern to me. Imagine that this and $this refer to an object that already has a getString method that returns an array of strings.
Now, when functA is called on that object, it will create a base object, and store the original this.getString function on it. Then, it will overwrite the this.getString method with an own definition.
This new version of the method will call the original function (which is referred to as base.getString) on the $this object, and return its result but slightly modified (extended by the "ab","cd","ef" array elements).
var base = {}; // I don't understand this line
It's not strictly necessary actually. One could equally have just directly stored the original function in a variable, there is no need to create this base object:
function functA() {
var original_getString = this.getString;
this.getString = function new_getString() {
var strings = original_getString.call(this);
return strings.concat(["ab","cd","ef"]);
};
}
Related
Here is what I want:
var Validator = function () {
this.do = function () {
alert(INTANCENAME); /// SHOULD BE 'FOO'
}
}
var FOO = new Validator().do();
Is it possibe to implement in Javascript?
The truth is there is no point of doing that, the only way I can hardly think is to loop all window or scope objects and check some kind of equality with the current object, something like
this.do = function () {
for(var key in window) {
if(this === window[key]) {
alert(key);
}
}
};
In order to work call it after you assign it.
var FOO = new Validator();
FOO.do();
Another issue that can come up is that an instance (a reference) can be stored in various variables so maybe will not get what you expect.
The literal answer to your question would be:
Use (new Error()).stack to get information on the line and the function where the do() method was called.
Use JS parser (e.g. Esprima) to find out what variable it was called on (if any, the method itself might be assigned to a variable).
I do not recommend doing this though.
There's no way to directly do what you're asking for here. Objects themselves are not in any defined by their matching variable name - in fact it's possible to have objects that exist that are not directly assigned to a variable, and multiple variables assigned to the same object.
The javascript interpreter uses our variable names as identifiers to help with the code execution, but once it's running the variable name makes no difference to the running javascript program, as it's probably been reduced to a memory reference by the time it's executing, completely separated from the original code that you wrote.
Edit: Answer by yannis does kind of simulate this, but it relies on working with variables available in a specific scope - what I ment was that there's no direct way to do this from within the object itself as per your example in the question.
Other than tricking existing functions that already implement this as something, why would you want to write a javascript function so that you need to alter its context (via .call or .apply) rather than explicitly passing the "context" as another parameter? Is there a performance benefit?
Example:
function tryIncrement(inc, context) {
context = context || this; // just so we can reuse same fn for the example
if( typeof context.val!= typeof 1|| typeof inc != typeof 1 ) return false;
context.val += inc;
return true;
}
var a = {name: 'A', val: 5}, b = {name: 'B', val: 20};
// reassign internal context
for(var i = 0, n = [1,3,"not a num",5]; i < n.length; i++) {
if( tryIncrement.call(a, n[i]) ) console.log('incremented', i, n[i], a);
else console.log('failed to increment', i, n[i], a);
}
// provide explicit context;
// could just as easily declared function so context was first param
// so it looked the same as previous implementation
for(var i = 0, n = [1,3,"not a num",5]; i < n.length; i++) {
if( tryIncrement(n[i], b) ) console.log('incremented', i, n[i], b);
else console.log('failed to increment', i, n[i], b);
}
There are many cases where you may wish to use this instead of passing an extra parameter. Consider the following function for example:
Function.prototype.async = function () {
setTimeout.bind(null, this, 0).apply(null, arguments);
};
This function allows us to defer a function call as follows:
alert.async("This will display later.");
alert("This will display first.");
You can see the demo here: http://jsfiddle.net/AjwQu/
Instead of binding the function to this we could have passed it as a parameter instead:
function async(funct) {
setTimeout.bind(null, funct, 0).apply(null, [].slice.call(arguments, 1));
}
We would use it like this now:
async(alert, "This will display later.");
alert("This will display first.");
The result is the same: http://jsfiddle.net/63dBF/
However to get the arguments we have to use [].slice.call(arguments, 1) instead. In the first example we could simply use arguments as the function was not a part of the argument list.
Everything has it's advantages and disadvantages. You just need to know what to use when. Hope this helps a bit.
Bonus: It's really easy to convert a function that uses this into a function that accepts an extra parameter and vice versa. First let's define a few utility functions:
var functProto = Function.prototype;
var bind = functProto.bind;
var bindable = bind.bind(bind);
var callable = bindable(functProto.call);
var appliable = bindable(functProto.apply);
The bindable function allows you to create a bindable version of an existing function which when called returns a new function bound to the given arguments.
The callable function allows you to create a callable version of an existing function which when called calls the existing function with the given arguments and this pointer.
The appliable function allows you to create an appliable version of an existing function which when called applies the given arguments and this pointer to the existing function.
Then given the function in the first example we can create the function in the second example as follows:
var async = callable(functProto.async);
See the demo here: http://jsfiddle.net/3dSBS/
Similarly we can convert the function in the second example into the function in the first example as follows:
Function.prototype.async = function () {
return async.apply(null, [this].concat([].slice.call(arguments)));
};
See the demo here: http://jsfiddle.net/rJQyS/
As you can see it's much easier to write a function using this and then construct the function accepting the context as a parameter from it than the other way around.
As far as I can tell the use of this isn't really any different than
another parameter, it just has a more complicated way of being
modified.
I think the easiest way to answer your question is to imagine if the creator of the base Javascript language had followed your conventions.
A world without this
A world without this is a scary noisy place with lots of excessive duplication:
var arr = [1,2,3,4];
arr.reverse(arr); //4321
More opportunities for misleading or verbose syntax
var str = "stringtobesplit";
"abiglongstringnotbeingsplit".split(str,":");
String.prototype.split(str,":");
And its not at all rid of apply at least:
Math.max.apply(arr); //didn't add the initial `this` since it doesn't exist
Effectively there would be a choice between creating only global functions, or creating functions on prototypes or objects that made assumptions about the types of the arguments it was receiving but didn't enforce those assumptions. For instance imagine the toString method in our fantasy world.
You could either create a global toString method which would take in an object of every type ever, and try to make them all work, or you could have a function on the prototypes of each type as it works currently, with no enforcement that it would be called on that type. Someone could call
Array.prototype.toString(str)
And we would need to handle it gracefully (for what its worth doing this with apply seems to revert to the Object.prototype.toString and returns [Object String]). So we would need to identify the correct prototype method to call in those cases, which means my guess is that the convention would be to call
str.toString(str)
or something along those lines.
So whats the point?
this is built to handle the common case for javascript methods on the prototype chain. It gives us a shorthand to allow an object to act on itself without duplicating the call to it or having to know exactly what its prototype is. Without it, we would either have to have no functions on objects, or would have to explicitly call the function on itself every time, introducing extra syntax and potential errors.
call and apply are the exception cases, and apply at least would have uses even if this went away. Its never a good idea to write your apis to the exception cases. If you're creating object oriented code, you should use this as an easy way to refer to the object that is the context for the call. If you write this well, then call and apply should be used rarely and in special situations.
TL;DR - this was designed as part of Javascript for a reason, use it when you're creating methods on objects for more clear and understandable syntax.
When you do object oriented programming your functions WILL depend on the context and it does not make sense do provide it as a parameter, as this would deafeat the purpose of object oriented programming.
It also makes sense to provide an implicit context for callbacks. You do not have to remember the correct order of the parameters if you only need the context. You would not have to use parameters at all in that case. So instead of
function mayCallback(param1, param2, context)
you could just write
function myCallback()
and use this, if you do not need param1 and param2.
To address my main purpose -- is there a performance benefit using this over a function parameter? -- the answer seems to be no:
http://jsperf.com/function-context-vs-parameter
Although there seems to be a slight benefit (may not be significant, however) around using parameter values instead of instance (this) variables within objects.
(Please test for yourself and comment if it's different)
Regarding the purpose being addressed by the other answers: there are some neat use cases as pointed out by #Aadit, maintainability is debatably a personal preference, but like #ben336 said if you're working with Objects (and thus OOP) then this can be more useful.
The ECMAScript 5th-edition native function bind may be an interesting bridge between the two worlds, or at least a time-sucking tangent to explore.
The instance vs parameter values test referenced above may also be a good example of my point -- if you're building a static library of functionality, you can "hijack" obj.callback2 by scoping to a different this, or just call obj.callback directly on your alternate context.
I'll admit I'm flailing around, cobbling code together from different authors in an attempt to figure out javascript prototypes.
I'm new to the prototype concept, and would like to have some instance variables in my class that can be modified using a method.
Here's what I'm trying, in essence. This was cribbed and modified from the web:
var MyGlobe = function () {
var self = this;
self.variable1 = null;
return self;
}
MyGlobe.prototype = function () {
var setup = function () {
this.variable1 = 33;
};
return {
setup:setup
};
}();
...the point of all that is so I can call the setup method on an instance of MyGlobe and set variable1 properly:
var aGlobe = new MyGlobe();
aGlobe.setup();
//aGlobe.variable1 is 33 now
This actually seems to work, but I'm not sure why the original author did things this way? For instance, what's the point of the self.variable1 bit at the beginning?
Is it preferable to typing out:
MyGlobe.prototype.variable1;
MyGlobe.prototype.variable2;
//....
I also thought you'd do something like self=this if you thought your class would be used in a callback function for example, but that doesn't appear to be the case here? (Happy to be shown wrong.)
I'm not sure what the best practices are here and would like to know more.
This actually seems to work, but I'm not sure why the original author did things this way? For instance, what's the point of the self.variable1 bit at the beginning?
None (for using self), the "declaration of instance properties" (even if only initialising them to null) can help engines to use more memory-efficient internal structures - though it's not really necessary.
I also thought you'd do something like self=this if you thought your class would be used in a callback function for example, but that doesn't appear to be the case here?
Exactly. This small snippet really should be rewritten to
var MyGlobe = function () {
this.variable1 = null;
}
MyGlobe.prototype.setup = function() {
this.variable1 = 33;
};
Is it better to declare the instance variables in the constructor function (self.variable1) as opposed to adding them to the prototype (MyGlobe.prototype.variable1)?
That's simple. On the prototype it's no instance property any more. And please distinguish between variables (like self - which are local-scoped to the function) and properties (like prototype, setup or variable1 - which are "public" on the object).
I have the following javascript method:
function 123_test_function(){
}
The function is generated by java and sent to the client. The 123 is the id of the component so it could change. i.e I can have another function called 111_test_function()
I want to pass this function as a reference.
So I need to create the reference
var 123_test_function = function 123_test_function(){
}
In another js file inside an object I have a function that needs to use the 123_test_function reference like so:
useFunction(123_test_function);
The problem I'm having is which the 123 part of the function.
In this object I have a variable(uniqueID) which has the number at the beginning of the function.
I need the function call to be something like:
useFunction(uniqueID+"_test_function");
This doesn't seem to pass a function instead it passes a string.
Am I doing something wrong?
For one, identifiers (such as function names) cannot begin with a digit.
To solve your problem, use an object, like this:
// 1. define an object to hold all your functions
var allFunctions = {};
// 2. store any function with a unique string as the ID
allFunctions['123_test_function'] = function () {
// whatever
};
// 3. call the function
allFunctions['123_test_function']();
allFunctions[uniqueID + '_test_function']();
Objects are associative arrays. They store key/values pairs, so they do exactly what you want here.
Note that functions don't need a name in JavaScript, so I did not use on in step 2.
If the function is defined as global one, it will be a member of global object (window in case of browsers). Hence you can just do window['id_'+uniqueID+'_test_function'] to access your function
useFunction(window['id_'+uniqueID+'_test_function'])
(Identifiers cannot begin with numbers in JavaScript so I added the 'id_' prefix. You can of course change it to your liking.)
function test_function(number){
if(number == 1)
{
return function() {}
}
if(number == 2)
{
return function() {}
}
}
call the function like this
var func = test_function(1)
func();
As a couple of people have correctly pointed out, a function (or indeed variable) name cannot begin with a numeric. Also this syntax is wrong:
var 123_test_function = function 123_test_function(){
}
The correct syntax would be:
var 123_test_function = function() {
};
...although it should also be noted that the effect of this is exactly the same as a "traditional"
function 123_test_function() {
}
...declaration, in the context of the window object - since window is effectively the global scope of a JS environment in a browser, it doesn't matter how you define the functions, they will always be accessible from anywhere. Understanding exactly what each method of declaring a function means in Javascript is important - luckily, Douglas Crockford to the rescue once again...
People have suggested various methods for calling your named functions from the context of a string, which is basically attempting to use "variable variable" syntax, a subject that has been discussed on SO and elsewhere at length. The eval() approach should be avoided wherever possible - if you find yourself needing an eval() chances are you went wrong somewhere a while back. #Tomalak has the right idea with a collection of functions held in an object, but this still needs the slightly messy string approach to reference things that are actually being accessed by a numeric ID. The collection approach has the advantage of not cluttering up the window object with what are likely to be single/zero use members.
But the way I see it, all you actually need here is an indexed array of functions, where all you need is the numeric index in order to access them. I suggest you create your functions like this:
// Do this once at the top of your JS
var test_functions = [];
// Now, for each function you define:
test_functions[123] = function() {
// Do stuff here
};
// And when you need to call the functions:
var funcId = 123;
test_functions[funcId]();
I've heard from a variety of places that global variables are inherently nasty and evil, but when doing some non-object oriented Javascript, I can't see how to avoid them. Say I have a function which generates a number using a complex algorithm using random numbers and stuff, but I need to keep using that particular number in some other function which is a callback or something and so can't be part of the same function.
If the originally generated number is a local variable, it won't be accessible from, there. If the functions were object methods, I could make the number a property but they're not and it seems somewhat overcomplicated to change the whole program structure to do this. Is a global variable really so bad?
I think your best bet here may be to define a single global-scoped variable, and dumping your variables there:
var MyApp = {}; // Globally scoped object
function foo(){
MyApp.color = 'green';
}
function bar(){
alert(MyApp.color); // Alerts 'green'
}
No one should yell at you for doing something like the above.
To make a variable calculated in function A visible in function B, you have three choices:
make it a global,
make it an object property, or
pass it as a parameter when calling B from A.
If your program is fairly small then globals are not so bad. Otherwise I would consider using the third method:
function A()
{
var rand_num = calculate_random_number();
B(rand_num);
}
function B(r)
{
use_rand_num(r);
}
Consider using namespaces:
(function() {
var local_var = 'foo';
global_var = 'bar'; // this.global_var and window.global_var also work
function local_function() {}
global_function = function() {};
})();
Both local_function and global_function have access to all local and global variables.
Edit: Another common pattern:
var ns = (function() {
// local stuff
function foo() {}
function bar() {}
function baz() {} // this one stays invisible
// stuff visible in namespace object
return {
foo : foo,
bar : bar
};
})();
The returned properties can now be accessed via the namespace object, e.g. ns.foo, while still retaining access to local definitions.
What you're looking for is technically known as currying.
function getMyCallback(randomValue)
{
return function(otherParam)
{
return randomValue * otherParam //or whatever it is you are doing.
}
}
var myCallback = getMyCallBack(getRand())
alert(myCallBack(1));
alert(myCallBack(2));
The above isn't exactly a curried function but it achieves the result of maintaining an existing value without adding variables to the global namespace or requiring some other object repository for it.
I found this to be extremely helpful in relation to the original question:
Return the value you wish to use in functionOne, then call functionOne within functionTwo, then place the result into a fresh var and reference this new var within functionTwo. This should enable you to use the var declared in functionOne, within functionTwo.
function functionOne() {
var variableThree = 3;
return variableThree;
}
function functionTwo() {
var variableOne = 1;
var var3 = functionOne();
var result = var3 - variableOne;
console.log(variableOne);
console.log(var3);
console.log('functional result: ' + result);
}
functionTwo();
If another function needs to use a variable you pass it to the function as an argument.
Also global variables are not inherently nasty and evil. As long as they are used properly there is no problem with them.
If there's a chance that you will reuse this code, then I would probably make the effort to go with an object-oriented perspective. Using the global namespace can be dangerous -- you run the risk of hard to find bugs due to variable names that get reused. Typically I start by using an object-oriented approach for anything more than a simple callback so that I don't have to do the re-write thing. Any time that you have a group of related functions in javascript, I think, it's a candidate for an object-oriented approach.
Another approach is one that I picked up from a Douglas Crockford forum post(http://bytes.com/topic/javascript/answers/512361-array-objects). Here it is...
Douglas Crockford wrote:
Jul 15 '06
"If you want to retrieve objects by id, then you should use an object, not an
array. Since functions are also objects, you could store the members in the
function itself."
function objFacility(id, name, adr, city, state, zip) {
return objFacility[id] = {
id: id,
name: name,
adr: adr,
city: city,
state: state,
zip: zip
}
}
objFacility('wlevine', 'Levine', '23 Skid Row', 'Springfield', 'Il', 10010);
"The object can be obtained with"
objFacility.wlevine
The objects properties are now accessable from within any other function.
I don't know specifics of your issue, but if the function needs the value then it can be a parameter passed through the call.
Globals are considered bad because globals state and multiple modifiers can create hard to follow code and strange errors. To many actors fiddling with something can create chaos.
You can completely control the execution of javascript functions (and pass variables between them) using custom jQuery events....I was told that this wasn't possible all over these forums, but I got something working that does exactly that (even using an ajax call).
Here's the answer (IMPORTANT: it's not the checked answer but rather the answer by me "Emile"):
How to get a variable returned across multiple functions - Javascript/jQuery