I wanted to have a method of adding functionality to pre-existing functions, so I made this:
Function.prototype.attachFunction = function(toAttach)
{
var func = this; //This is the original function, which I want to attack toAttach function to.
//Can I do this without wrapping it in a self-executing function? What's the difference?
func = (function()
{
return function()
{
func();
toAttach();
}
})();
return func; //Return the newly made function, not really important.
}
I paste this into the Google Chrome console, and there are no errors, however, it does not (or so it would seem) alter the original function at all.
f = function() {console.log("g");};
f.attachFunction(function(){console.log("New function!");});
f(); //Prints out just "g".
When attachFunction executes, it returns a function which executes func() and toAttach. However, if you change your code to be the following, it will attempt to execute both functions, where currently the old f is still called at the end.
f = function() {console.log("g");};
f = f.attachFunction(function(){console.log("New function!");});
f(); //Causes an infinite loop since calling func() is the same as calling this()
To merge two functions we need to wrap them the same way but not while extending Function
var func1 = function(){
console.log('g');
};
var func2 = function(){
console.log('New function!');
};
func1 = (function(f1,f2){
return function(){
f1();
f2();
}
}(func1, func2));
func1(); //Writes out both g and New function!
The reason I pass in func1, and func2 as parameters is to prevent the same problem of getting into an infinite loop. I want to maintain a reference to these functions at that point in time.
A helper function would then be the following
function combineFunctions(f1, f2){
return function(){
f1();
f2();
}
}
and would be used like this
var f = function() {console.log("g");};
f = combineFunctions(f,function(){console.log("New function!");});
f();
The attachFunction method you've set on the Function prototype is a higher-order function, or combinator, that accepts a function and returns a new function. It is inherited by any function created thereafter, as expected. However, when it is called it does not alter the state of f in any way, it simply produces a new function that calls f, or the calling function rather.
So, if you wanted to see both console.log messages, you simple need to call the function it returns, like so:
f.attachFunction(function(){console.log("hi")})();
or more simply:
f.attachFunction(f)();
Note that although functions are objects, the execution context (code) of f is not a property of f such that it can be manipulated directly, it is kept in an internal attribute.
Underscore.js' wrap() function should be quite close to what you want.
Currently, you're trying to call a variable as if it were a function (toAttach is a variable and you're smacking some parenthesis on the far side of it). Consider this: toAttach may CONTAIN a function, but that does not make it a function (much like a grocery store is not an apple). Instead you need to call the function contained within the variable.
There are several ways to do this (although only one or two apply here), none of the [right] ways involve eval() (life lessons).
Consider this thread. Pass the function name as a string and then use
window[toAttach]();
to call the function. It's a bit hacky, and lacks the finesse of passing the function as an object, but it works.
Alternatively (completely depending on your needs) you can bind the function to an event. If you're extra sneaky (and why not?) you can use
setTimeout(toAttach, 0);
Where toAttach is a reference to the actual function (again).
Finally, and best, I believe, is the Function.call() method. Using this, you can call a function stuffed in a variable, and even pass it a context for this.
toAttach.call([Context]);
Where [Context] is the context of the function (ie, what this refers to when inside of the function, in most cases it can be left blank to get the desired scope). I can't say I've tested it under your certain circumstances (thus why I have included it last), but I believe it should give you the results you're looking for.
Here's my attempt to achieve this, it is not clean as if it was entirely in the prototype but it works. There are probably better ways than mine.
var bindings={};
function execBindings(func_name) {
if (bindings[func_name] != undefined) {
for (var i=0;i<bindings[func_name].length;i++) {
bindings[func_name][i]();
}
}
}
Function.prototype.bind=function(action){
if (bindings[this.name] == undefined) {
bindings[this.name]=[];
}
bindings[this.name].push(action);
}
Then, to use the binding :
function f() {
alert("foo");
execBindings("f");
}
f.bind(function(){
alert("bar");
});
f.bind(function(){
alert("test");
});
f();
which results in 3 alerts, in the order thwy were binded to the function.
There are two problems I just found.
problem 1.
f = function() {console.log("g");};
f.attachFunction(function(){console.log("New function!");});
f();
It definitely doesn't work, cause attachFunction just wrap around your original function and return the wrapped, it doesn't change the original function, which means your f function is still f = function() {console.log("g");}
Problem 2.
If you reassign f with the result of attachFunction, an Maximum call stack size exceeded will occur. In the definition of attachFunction:
func = (function()
{
return function()
{
func();
toAttach();
}
})();
return func;
The func function call himself recursively.
Update
I prefer this approach.
Function.prototype.attachFunction = function(toAttach)
{
var that = this;
func = (function()
{
return function()
{
that();
toAttach();
}
})();
return func; //Return the newly made function, not really important.
}
f = function() {console.log("g");};
f = f.attachFunction(function(){console.log("New function!");});
f();
Related
I am just getting more into javascript and wandering what is the difference between
var myfunc = function(){
publicfunctions = {}
publicfunctions.function1 = function(){do smthing and return}
return publicfunctions
}
and
var myfunc = function(){
this.function1 = function(){do smthing and return}
}
It seems to me that both doing the same thing
Also can someone explain what is difference between
var func = (function myfunc(){ .. do smthing and return .. })();
and
var func = function myfunc(){ .. do smthing and return .. }
var newfunc = new myfunc()
Thanks
Let's go step by step.
example:
a) you define a function that returns an object (careful with variable declaration - you should declare it with var keyword in order to scope it to your function. That objects has a single property that points to a function. Never the less, your first function is assigned to a variable myfunc
Now, if you try to call myfunc(), you'll get an object with single property function1. Nothing special here.
b) you define a function again and assign it to myfunc variable, only this time it contains this keyword which assumes you're trying to utilize this function as a constructor. In this example, merely calling myfunc produce no output since you haven't returned anything from a function. However, calling a function with preceding keyword new will result in object creation.
var myObj = new myfunc();
// `this` keyword now refers to myObj which means myObj can call `function1`
example:
a) On the righthand side is something that is called IIFE (or Immediately Invoked Function Expression). Basically means, a function expression that is created and executed, well, immediately. So func should receive whatever that function returns.
b) Yet again, facing a constructor, only this time you actually assumed myfunc is a constructor when you added new keyword before myfunc execution. Creates an object to whic newfunc now points to and has authority over.
Note:
In constructor functions (the ones that you call with new keyword), this is implicitly returned and no need for explicit return. Now, if you want to test it and return something else instead, I'll leave it up to you to explore and see what you'll end up with. :)
Since it's a broader topic in itself, I recommend this excellent book by Nicholas Zakas. It really answers a lot of JS questions.
I noticed a difference when calling a function with empty parentheses, or without any parentheses at all. However, I am not passing any arguments to the function so I wondered, what would be the difference between:
window.onload = initAll();
and
window.onload = initAll;
Please explain the principle behind it.
window.onload = initAll();
This executes initAll() straight away and assigns the function's return value to window.onload. This is usually not what you want. initAll() would have to return a function for this to make sense.
window.onload = initAll;
this assigns the actual function to window.onload - this is possible because in JavaScript, as #Felix says, functions are first class objects - without executing it. initAll will be executed by the load event.
You may also see something like this:
window.onload = () => initAll();
This will create a new function that, when called, will call initAll immediately. Parentheses are necessary here for that "call initAll immediately" part to work. But, because it's wrapped in a function, nothing will execute until that outer function itself is called, and you assign the reference of that outer function to window.onload, so initAll will also be executed on the load event.
What Pekka says is correct, but I want to elaborate a little with an example that will help explain to someone who doesn't fully understand function pointers or delegates.
I won't use window.onload because that's a bit contrived to demonstrate. I'll use a simple multiply function to demo instead:
function Multiply(operator, operand) {
return operator * operand;
}
This could equally be written:
Multiply = function(operator, operand) {
return operator * operand;
}
While in the first example, the implication may not be obvious, the second example shows more clearly that we're assigning a function which has 2 parameters to a variable called Multiply, and this concept of functions as assignments is common throughout JavaScript. This is a small demonstration of the fact that functions are "first class citizens", that is, they can be passed around exactly as if we were passing around values.
So now to the difference of assignment:
var operator = 3;
var operand = 4;
var ret = Multiply(operator, operand);
At the point of defining the ret variable, Multiply is executed and the return value is assigned - ret becomes equal to 12.
Let's try that again a different way:
var operator = 3;
var operand = 4;
var ret = Multiply;
Now, at the point of defining ret, ret becomes your Multiply function as opposed to being the result obtained from your Multiply function. Calls to ret() will cause your Multiply function to be executed, and you can call it exactly as if you'd called Multiply(operator, operand):
var out = ret(3, 4);
is the same as
var out = Multiply(3, 4);
You have effectively said that you are going to use ret as a delegate for Multiply(). When calling ret, we're really referring to the Multiply function.
Back to your window.onload. Think of this as:
window.onload = function() {
//Doing what all good window.onload functions should do...
}
initAll = function() {
return 12;
}
So as you can see, window.onload is a function just like any other function, there's nothing special about it. You can assign it a value, assign it a function, null it out if you wish - the point is that there's nothing any more special about window.onload than there is about your own function. The only slightly different thing is that it gets called by the window when it's loaded. [Disclaimer: I've never actually nulled out window functions, so I'm not sure if this will cause negative repercussions. One would hope they check to see if a function is assigned before calling it i.e. if (window.onload) window.onload();].
Now calling initAll() what we're saying is:
window.onload = initAll();
which might as well say:
window.onload = 12;
But when we say initAll without the parentheses, what we're really saying is: I want to replace whatever my window.onload function is, with a new function - i.e. I want to replace it with my initAll function, so that any calls to window.onload runs my initAll code.
So:
window.onload = function() {
//Doing what all good window.onload functions should do...
}
is replaced with:
window.onload = function() {
return 12;
}
So any call to window.onload will execute your initAll function instead of whatever window.onload was originally. You have replaced the original function with your new function.
In fact, you could equally write:
window.onload = function() {
//Write all your init code right in here instead of having a separate
//initAll function.
}
Another example that may demonstrate better is this:
var d = new Date();
var currentTime = d.getTime();
Whatever the time was at the time d is defined ends up assigned to currentTime. Great, but that's only useful if we want to find out what time the function containing that code was called - i.e. at page load time. What if we want the current time any time that currentTime is called?
var currentTime = function() {
var d = new Date();
return d.getTime();
}
var a = currentTime(); //The current time at the point a is defined...
var b = currentTime; //b is a functional reference to currentTime...
var c = b(); //The current time when variable c is defined
var d = c; //The current time when variable c was defined
Notice how we call b() in our c and d assignments exactly as we could call currentTime()?
Functions in javascript are first-class citizens, and as such, can be assigned to other variables or passed around as arguments.
So, when you do
window.onload = initAll;
You are setting the onload property of the window object to reference the initAll function itself.
When you do
window.onload = initAll();
You are setting the onload property to hold the return value of initAll, since it will execute in place on that line.
I'm 6 years late but I feel this could have been explained a lot simpler than the above answers.
So here is the TLDR; or bird's eye view when calling functions using and not using ()'s
Lets take this function for example:
function foo(){
return 123;
}
if you log "foo" - without ()
console.log(foo);
---outout------
function foo(){
return 123;
}
Using no () means to fetch the function itself. You would do this if you want it to be passed along as a callback.
if you log "foo()" - with ()
console.log(foo());
-----output-----
123
Using () after a function means to execute the function and return it's value.
initAll is a reference to a function value and the brackets operator appended to the function name RUNS this function object.
So if you do something like
a = initAll
then a will become the same as initAll - for example you can do a() - but with
a = initAll()
the variable a will get the return value of the executed initAll function
Up until now, I've always used var self = this before creating a function that would need access to its parent. However the bind() method seems like a more appropriate way to do so and I'm exploring that option, along with the apply() and call() methods.
This is what I came up with to compare all three:
jsFiddle
(function(){
this.say = function(text){
console.log(text);
}
this.run = function(){
console.clear();
setTimeout(function(){
this.say('bind');
}.bind(this), 1000);
setTimeout(function(){
this.say('call');
}.call(this), 1000);
setTimeout(function(){
this.say('apply');
}.apply(this), 1000);
}
this.run();
})();
But the script leaves me with some questions:
Why don't the call() and apply() methods respect the timeout like the bind() method does and which one should I use?
Is there any difference between the following syntaxes which behave similarly:
setTimeout( function(){ this.say('bind'); }.bind(this) , 1000);
setTimeout( (function(){ this.say('bind'); }).bind(this) , 1000);
setTimeout( (function(){ this.say('bind'); }.bind(this)) , 1000);
You're missing a key point here (but the key point is very obfuscated in documentation).
You know whenever you write a function like this:
function something() {
// ... whatever
}
It's just a function reference sitting there by itself. It hasn't been called yet.
When you write something like this:
(function something() {
})()
Or this:
function something() { ... }
something();
You've now called the function. Those are two very completely different concepts.
In the first one where the function is just sitting there without having been called, it's referred to as a function reference, and that's exactly what .bind returns: a function reference.
.call and .apply return the return value of whatever function, in the new context. So in fake JavaScript la-la land, it would look something like this:
function() {
}.bind(this)
// returns a function reference: function() { }
Whereas:
function() {
return 'hello';
}.call(this)
// returns hello... NOT A FUNCTION REFERENCE!
You see...
You would probably never do something like this:
function hello() {
return true;
}
setTimeout(hello(), 100);
You'd get an error: setTimeout expected a Function, and it received a Boolean, or something like that.
^ That's not a very semantic error, but it's an error nonetheless.
But, what you would do is something like this:
function hello() {
return true;
}
setTimeout(hello, 100);
See the difference? That last example is okay, because you passed in a function reference.
Because internally, setTimeout does something like this:
window.setTimeout = function(callback) {
// a bunch of other stuff, and...
callback();
};
As far as your second question goes...
Those are pretty much all equivalent. Closures make sense though whenever you're declaring variables that you don't want to give other objects access to.
To help you understand closures a little bit, let's pretend we're not even talking about JavaScript.
In math, you know how you can do something like a + b * c?
Well, when you group them by parentheses, it kind of changes the behavior: (a + b) * c.
Now, obviously that's not quite related to JavaScript in the sense that in JavaScript we're not worried about order of operations (unless you're actually doing math in JavaScript), but the whole idea is that those parentheses just act as a container (what we call a closure) for whatever is inside of it.
So when you put a function inside parentheses, you're just hiding that function from the outside world, but it can still return stuff, and it can still have access to parent scopes (like window, for example).
A cool example:
var name = (function(name) {
return name
})(function() {
return 'Jane';
}());
console.log(name); // => Jane
Both .call and .apply execute the functions on which they are called immediately. What this means is that in those cases you are passing the result of call or apply on your anonymous function to setTimeout and that result is undefined because those functions don't return anything.
bind on the other hand returns a new function, which you are then correctly passing to setTimeout. To get call and apply to behave similarly, move them inside the anonymous function:
setTimeout(function(){
this.say.call (this, 'call');
}, 1000);
for example.
Afaik those are equivalent.
I am stumbling upon a problem that I have seen before, but that I couldn't solve before. I will likely stumble upon it again in the future, so please, someone explain it to me what is going on?
In the partial snippet of javascript below, I have a function that populates a screen, including an order combobox (twitter bootstrap). When I click on one of the order items in that combobox, it should invoke the function clsModCampaigns.blnCompaniesListReload().
For a reason that I don't understand, once inside the '$.each' iterator, the global object reference 'objModCampaigns' is lost? I get a successful alert '1', but not an alert '2'.
Within the $.each, I would like to use 'objModCampaigns.arrOrderBy' instead of 'this.arrOrderBy', but the $.each iterator only seems to work this way. Why is it working this way??
What is going on with 'this', or with variables/objects assigned in the root of the class with 'this'?
Is $.each just special??
function clsModCampaigns(objSetSystem, objSetModuleBase)
{
objModCampaigns = this;
arrOrderBy = {
intID: 'ID',
strName: 'Name'};
[...]
this.blnScreenCampaignInitialize = function (fncSuccess,fncError, intID) {
$.each(this.arrOrderBy, function (strFieldName, strFieldDescription) {
if(strFieldName != 'datDeleted' || objSystem.blnHasPerm("CAMPAIGNS_DELETED")) {
strOrderByID = "ulCampaignsCompaniesListOrderBy" + strFieldName;
$("#ulCampaignsCompaniesListOrderBy").append('<li>'+strFieldDescription+'</li>');
$("#"+strOrderByID).unbind("click").bind("click", function() {
alert("1");
objModCampaigns.arrCurrentShownCompanies.strOrderBy = strFieldName;
objModCampaigns.blnCompaniesListReload();
alert("2");
});
}
});
return true;
};
}
The code you have is
$.each(this.arrOrderBy, ...);
You want
$.each(arrOrderBy, ...);
The reason for it is the this context on that line is different because it is inside a new function this.blnScreenCampaignInitialize.
This is just a part of how JavaScript works
var message = "hello";
function welcome() {
console.log(message);
}
welcome(); // "hello"
P.S. use var
If you don't use var, you'll be attaching all of your vars to the global object.
function hello() {
foo = "bar";
console.log(foo);
};
hello(); // "bar"
console.log(foo); // "bar"
// Holy smokes! `foo` has escaped our `hello` function!
Compare that to
function hello() {
var foo = "bar";
console.log(foo);
}
hello(); // "bar"
console.log(foo); // ReferenceError: foo is not defined
// much better
Now let's see a terrible example
function a() {
b = 5;
return b;
}
function b() {
return "function";
}
console.log(a()); // 5
console.log(b()); // TypeError: number is not a function
This is happening because we didn't use var properly. We first define b as a function but after running a(), b is now set to 5. The second log statement is the equivalent of trying to run 5() because b is no longer a function.
P.P.S. it's pretty unconventional to prefix your vars with str, int, fnc, obj, or cls in JavaScript.
I understand you're a "VB guy" according to your comments, but that's no excuse for bringing your own conventions to the language. I see in your profile that you're fluent in Dutch, English, German, and French. I would recommend you treat learning programming languages much the same as spoken languages: each of them have their own explicit set of rules and conventions.
Here's a heap of free JavaScript books for you. I hope they can help you learn some more basics.
P.P.P.S. Overall, your function is really big as it is, and I can see you already truncated some of the code with your [...]. The whole thing could probably benefit from some better composition.
If you paste all of your code, maybe someone could help you better.
What is going on inside the $.each() ?
Regarding you question title, I'm trying to answer:
// each function in source
function (obj, callback, args) {
//...
}
Check the source of complete $.each function by yourself, you can see any function's source code just by typing the function name in the appropriate text box (the second on top).
Here in each function, the array/object passed in to the each function (the first argument) is being run through a loop and each value is being passed in to the callback (second argument) and that call back is getting executed like:
callback.apply(obj[i], args);
So, the passed callback in the each function is being executed each time the loop occurs ad the current value in the loop is passed as the argument of callback function along with the third argument args.
If your function function clsModCampaigns(){ //... } is a normal function then this inside this function points to global window object. so just use:
$.each(arrOrderBy, ...);
instead of
$.each(this.arrOrderBy, ...);
Because, arrOrderBy is within the direct scope so arrOrderBy is accessible directrly. For example:
function someThing()
{
var x = 'y'; //<-- this scope (everything inside someThing) is
// global for somethingElse inner function
function someThingElse)(x) //<-- possible to use directly
{
}
}
The keyword this behaves differently depending on the context. Check about this on MDN.
I have a function like this:
function run(arg) {
if (!window.alreadyRun) init();
window.alreadyRun = true;
/* more code */
}
You get the idea, I'm trying to figure out if it's the first time a function is called.
Is there a better way to do this? Without using globals? Something like this:
function run(arg) {
var ranAlready;
if (!ranAlready) init();
ranAlready = true;
/* more code */
}
This will return a function, with a variable called runCount which will hold the number of times it was called.
var yourFunction = function() {
var runCount = 0;
return function() {
console.log(runCount);
runCount++;
}
}
var a = yourFunction();
a(); // runCount: 0
a(); // runCount: 1
a(); // runCount: 2
a(); // runCount: 3
See it on jsFiddle.
If you just want to run an init type function, you could place the code above returning the inner function. It will be called once before returning the inner function, and its scope will retain to its outer function.
The power of closures.
var f = (function(run) {
return function() {
if (!run) init(),run=true;
// do code
};
}(false));
You can even use if (!run) init() && run = true and get init to return false if you want it to be called again on the next function call.
We have a self executing function which creates a local run variable and set's it to false by passing it in as an argument. We then have a single line which checks if it's false if so it does init(), run=true which is running the init function and assigning it to true in a single expression.
Basically anywhere were your using global scope to make the variable static to the function you can instead use a closure as a scope level between local function scope & global scope.
If you need a variable that is static to a function & read only you can use the little known const keyword.
I think closures are completely overkill for this, and only complicates the code.
What you're describing is known as a static variable in Object Oriented languages, and it can be mimicked quite easily in JS by attaching properties directly to the function. This is possible because functions are first-class objects in JS:
function run(arg) {
if (!run.ranAlready) { // run.ranAlready is undefined at first, so falsy
run.ranAlready = true;
init();
}
/* more code */
}
This is far simpler than nested functions, and you can continue to use run() in exactly the same way.
Another advantage is that, for unit testing, you can still access the ranAlready property from outside the function to check that your code is working correctly:
assert(run.runAlready == false);
run();
assert(run.runAlready === true);
Granted, this can't be used for anonymous functions, such as in event handlers, but isn't it much cleaner to give that anonymous function a name instead of using nested functions and an extra function invocation?
Here's just another way to do it. You can have the function modify itself. In the case below, myfunction gets changed to a new one. This may not be exactly what you're looking for but I think it's useful to at least post this so you can see alternative ways to do things (and also: self modifying code can just be cool at times).
var myfunction = function() {
alert("This is the first time I'm executed");
myfunction = function() {
alert('Subsequent times');
}
}
myfunction(); // displays the alert 'This is the first time...'
myfunction(); // displays the alert 'Subsequent times'
myfunction();
Example: http://jsfiddle.net/jonathon/wntmB/