Assign an already-defined function to a variable with set arguments - javascript

I'd like something equivalent to this code, except I don't want my_func to be called when my_var is defined. I want to call my_var() later on in the code with the original argument ('called!') preserved.
function my_func(first_arg) {
alert(first_arg);
};
var my_var = my_func('called!');
How?

Your function will be called when the variable is initialized (and the variable will then hold the output of your function, which isn't what you want). Why not make another function that returns the output of your function?
I'm bad at explaining things, so here's some code to stare at:
var my_var = function() { return my_func('called!'); };

You might be looking for something like Function.prototype.bind, which allows you to bind a function with arguments to a particular context. Basically, it allows you to do this:
function myFunc(firstArg, secondArg) {
alert(firstArg + secondArg);
};
var myVar = myFunc.bind(null, 'called!');
myVar(' - from myVar!');
// result is alert with -> "called! - from myVar"
It's not in older browsers, but the link above has a compatibility implementation to make it work for this particular scenario.

The straightforward way to implement this would be wrapping a call to your function with an argumentless anonymous function:
var my_var = new function() {
my_func('called!');
}
ECMAScript 5th Edition introduces the Function.bind method that implements partial application (or more specifically currying), that would let you write this the following way:
var my_var = my_func.bind(undefined, 'called!');
(The undefined is there because the first parameter of bind() binds a value to the this "parameter".)
Function.bind() is relatively recent and not widely implemented. The Mozilla documentation includes a simple shim you could use to get most of the functionality. John Resig also has a blog post with a different implementation of partial application. It might also be available in one of the many many JS libraries.

Make a new function!
function my_func(first_arg) {
alert(first_arg);
};
var my_var = function() {
my_func('called!');
}

Just need the function to return a function:
function my_func(first_arg) {
return function(){alert(first_arg);}
};
var my_var = my_func('called!');

Related

Override JS method i Java style [duplicate]

I would like to override a Javascript built-in function with a new version that calls the original (similarly to overriding a method on a class with a version that calls super in many languages). How can I do this?
For example...
window.alert = function(str) {
//do something additional
if(console) console.log(str);
//super.alert(str) // How do I do this bit?
}
Store a reference to the original function in a variable:
(function() {
var _alert = window.alert; // <-- Reference
window.alert = function(str) {
// do something additional
if(console) console.log(str);
//return _alert.apply(this, arguments); // <-- The universal method
_alert(str); // Suits for this case
};
})();
The universal way is <original_func_reference>.apply(this, arguments) - To preserve context and pass all arguments. Usually, the return value of the original method should also be returned.
However, it's known that alert is a void function, takes only one argument, and does not use the this object. So, _alert(str) is sufficient in this case.
Note: IE <= 8 throws an error if you try to overwrite alert, so make sure that you're using window.alert = ... instead of alert = ....
There is no "super". Anyway, create a closure to "keep" around the original function-object.
Note the "self invoking function" that returns a new function-object (that is assigned to the window.alert property). The new function-object returned creates a closure around the variable original which evaluates to the original value of window.alert that was passed in to the "self invoking function".
window.alert = (function (original) {
return function (str) {
//do something additional
if(console) {
console.log(str)
}
original(str)
}
})(window.alert)
However, I believe some browsers may prevent alert and other built-ins from being modified...
Happy coding.
I'm assuming your question is how do you overwrite a built-in and still be able to call it. First off as a disclaimer, you should never overwrite built ins unless you have a good reason for doing it since it will make it impossible to debug/test.
This is how you would do it:
window._alert = window.alert;
window.alert = function(str) {
if(console) console.log(str);
window._alert(str);
}
How to do simple classical inheritance in Javascript:
SuperClass.call(this) // inherit from SuperClass (multiple inheritance yes)
How to override functions:
this.myFunction = this.myFunction.override(
function(){
this.superFunction(); // call the overridden function
}
);
The override function is created like this:
Function.prototype.override = function(func)
{
var superFunction = this;
return function()
{
this.superFunction = superFunction;
return func.apply(this,arguments);
};
};
Works with multiple arguments.
Fails when trying to override undefined or nonfunctions.
Makes "superFunction" a "reserved" word :-)
JavaScript does not use a classical inheritance model. There is a nice article here which describes a way to write your classes so that a similar syntax can be used, but it's not natively supported.
By using proxy object you can do this.
window.alert = new Proxy(window.alert , {
apply: function(target,that,args){
console && console.log(args.join('\n'));
target.apply(that,args)
}})

Any reason to have a function as a variable?

Editing someone else's code, I ran across a pattern I had not previously seen:
var functionName = function functionName(){};
and sometime later, to call the function, using this jQuery
$(functionName);
Now, before I change it to the standard function functionName(){} called with functionName();, is there any reason to do it the other way?
EDIT: Updated to reflect the use of jQuery in the function call. I oversimplified the example. (Oops! Sorry!)
var workerFn = function someDefaultFn() {};
if ( lots of logic) {
workerFn = function specialFn() {};
}
//// later on
workerFn();
So now we have flexibility as to what exactly is invoked. Sort of a poor-man's polymorphism.In your example we'd be passing the workerfn to JQuery to be invoked, so same possibility for flexibility.
The only technical reasons for using a function expression would be to avoid hoisting of the function and/or being able to use another internal name to refer to the function itself.
These are the only differences between function expressions and function declarations and it depends on the context whether they are relevant at all.
I'd say it's a bug because functionName; will not do anything. Or is it a typo in your question?
functionName;
would not call the function. This is just a reference to the function. Calling the function needs the (). So if we have
var functionName = function test(){ alert("0");};
this
functionName;
does not call it. Actually this does not do anything at all (no-op). This is same as
var x;
x;
Only this
functionName()
calls it.
Maybe the functionName; is used for something else. We can tell only if we have context.
[EDIT]
You can find var functionName = function(){}; and make as many instance this way var second = functionName;
It's helpful only if you want to have few variables to call the same function, but with a different param...
But in your case, functionName will contain only that the function functionName() {}; will return.
You propably have something like this in the function content:
var functionName = function test(param) {
[...]
return function(otherParam) {
//do something
};
}

Use of 'this' in a JavaScript object using jQuery

Lately I've been trying to make an object in JavaScript with the following structure:
function colorDiv(div){
this.div=div;
this.div.bind("click",this.changeColor)
this.changeColor(){
this.div.css("background", "#FF0000");
}
}
The problem is that the changeColor method cannot be called from the jQuery environment because this must refer to the current colorDiv object, so the bind method cannot work as expected.
How can this be solved?
There are a couple ways. The simplest is as follows:
function ColorDiv(div) {
var that = this;
that.div = div;
that.div.bind("click", that.changeColor);
that.changeColor = function () {
that.div.css("background", "#FF0000");
};
}
var colorDiv = new ColorDiv($("#my-div"));
$("#something-else").click(colorDiv.changeColor);
You save a reference to this in the variable that, which is just the name commonly used in the JavaScript world for exactly this purpose. Then you refer to that instead of this inside your changeColor method. (Note that I used that everywhere, just for consistency, even though the only place it actually makes a difference is inside the changeColor method.)
Another is to use the Function#bind method. You can either use it every time you call changeColor, like so:
var colorDiv = new ColorDiv($("#my-div"));
$("#something-else").click(colorDiv.changeColor.bind(colorDiv));
or you can use it in the ColorDiv class to ensure that all methods are bound correctly whenever they are called:
this.changeColor = (function () {
this.div.css("background", "#FF0000");
}).bind(this);
As noted in the linked article, Function#bind is not supported in all browsers, so you'll need a shim like the one they give, or possibly a full-fledged ES5 shim.
Underscore.js has a bindAll function that could be useful here, too, especially with multiple methods:
_.bindAll(this);
Finally, it's worth noting you don't really need to do any of this in your particular example: just do
this.changeColor = function () {
div.css("background", "#FF0000");
};
instead of what you have, i.e. reference the div variable passed in, instead of the reference stored in this.div, since they are the same thing.
Try setting as the first line of the method:
var self = this;
and then using self as needed.
this.div.bind("click",self.changeColor)

How to pass 'this' along with a function?

I want to delegate some function calls from one object to another:
objA.feature = objA.component.feature;
(Assuming feature is supposed to be a function both in objA and in its component)
But that clearly doesn't work, because the reference to this gets stripped from the function and ends up being a completely different object when it gets called (it actually is objA instead of objB.component).
You need to write something like this in order to get it to work:
objA.feature = function() {
objA.component.feature.apply(objA.component, arguments);
};
Is there a shorter (idiomatic) way to do that?
There's a function called "bind" on the Function prototype in newer runtimes:
var newFunc = someFunc.bind(somethingThatShouldBeThis);
will make this refer to "somethingThatShouldBeThis" when "newFunc" is called.
You can steal code from something like the Functional library to provide a "bind" function in environments that lack a native one.
edit — here's the code from Functional:
Function.prototype.bind = function(object/*, args...*/) {
var fn = this;
var args = Array.slice(arguments, 1);
return function() {
return fn.apply(object, args.concat(Array.slice(arguments, 0)));
}
}
Pretty simple, eh? It just returns a function back to you that, when invoked, will call the first argument as a function, and also pass along whatever arguments you pass in to the result (that is, to "newFunc" in the example above). The main wrinkle is that this one also saves extra arguments passed in originally, which can sometimes be handy.
Here is a great article on scope:
Binding Scope in JavaScript
However, most JavaScript frameworks (MooTools, jQuery) have built in methods for this. jQuery uses "proxy" and MooTools uses "bind", so be sure to check the documentation of whatever framework you're using.
Your best bet is to use a createDelegate-style method like some of the frameworks do. A bare-bones implementation was posted on OdeToCode a few years ago.

What does (function($) {})(jQuery); mean?

I am just starting out with writing jQuery plugins. I wrote three small plugins but I have been simply copying the line into all my plugins without actually knowing what it means. Can someone tell me a little more about these? Perhaps an explanation will come in handy someday when writing a framework :)
What does this do? (I know it extends jQuery somehow but is there anything else interesting to know about this)
(function($) {
})(jQuery);
What is the difference between the following two ways of writing a plugin:
Type 1:
(function($) {
$.fn.jPluginName = {
},
$.fn.jPluginName.defaults = {
}
})(jQuery);
Type 2:
(function($) {
$.jPluginName = {
}
})(jQuery);
Type 3:
(function($){
//Attach this new method to jQuery
$.fn.extend({
var defaults = {
}
var options = $.extend(defaults, options);
//This is where you write your plugin's name
pluginname: function() {
//Iterate over the current set of matched elements
return this.each(function() {
//code to be inserted here
});
}
});
})(jQuery);
I could be way off here and maybe all mean the same thing. I am confused. In some cases, this doesn't seem to be working in a plugin that I was writing using Type 1. So far, Type 3 seems the most elegant to me but I'd like to know about the others as well.
Firstly, a code block that looks like (function(){})() is merely a function that is executed in place. Let's break it down a little.
1. (
2. function(){}
3. )
4. ()
Line 2 is a plain function, wrapped in parenthesis to tell the runtime to return the function to the parent scope, once it's returned the function is executed using line 4, maybe reading through these steps will help
1. function(){ .. }
2. (1)
3. 2()
You can see that 1 is the declaration, 2 is returning the function and 3 is just executing the function.
An example of how it would be used.
(function(doc){
doc.location = '/';
})(document);//This is passed into the function above
As for the other questions about the plugins:
Type 1: This is not a actually a plugin, it's an object passed as a function, as plugins tend to be functions.
Type 2: This is again not a plugin as it does not extend the $.fn object. It's just an extenstion of the jQuery core, although the outcome is the same. This is if you want to add traversing functions such as toArray and so on.
Type 3: This is the best method to add a plugin, the extended prototype of jQuery takes an object holding your plugin name and function and adds it to the plugin library for you.
At the most basic level, something of the form (function(){...})() is a function literal that is executed immediately. What this means is that you have defined a function and you are calling it immediately.
This form is useful for information hiding and encapsulation since anything you define inside that function remains local to that function and inaccessible from the outside world (unless you specifically expose it - usually via a returned object literal).
A variation of this basic form is what you see in jQuery plugins (or in this module pattern in general). Hence:
(function($) {
...
})(jQuery);
Which means you're passing in a reference to the actual jQuery object, but it's known as $ within the scope of the function literal.
Type 1 isn't really a plugin. You're simply assigning an object literal to jQuery.fn. Typically you assign a function to jQuery.fn as plugins are usually just functions.
Type 2 is similar to Type 1; you aren't really creating a plugin here. You're simply adding an object literal to jQuery.fn.
Type 3 is a plugin, but it's not the best or easiest way to create one.
To understand more about this, take a look at this similar question and answer. Also, this page goes into some detail about authoring plugins.
A little help:
// an anonymous function
(function () { console.log('allo') });
// a self invoked anonymous function
(function () { console.log('allo') })();
// a self invoked anonymous function with a parameter called "$"
var jQuery = 'I\'m not jQuery.';
(function ($) { console.log($) })(jQuery);
Just small addition to explanation
This structure (function() {})(); is called IIFE (Immediately Invoked Function Expression), it will be executed immediately, when the interpreter will reach this line. So when you're writing these rows:
(function($) {
// do something
})(jQuery);
this means, that the interpreter will invoke the function immediately, and will pass jQuery as a parameter, which will be used inside the function as $.
Actually, this example helped me to understand what does (function($) {})(jQuery); mean.
Consider this:
// Clousure declaration (aka anonymous function)
var f = function(x) { return x*x; };
// And use of it
console.log( f(2) ); // Gives: 4
// An inline version (immediately invoked)
console.log( (function(x) { return x*x; })(2) ); // Gives: 4
And now consider this:
jQuery is a variable holding jQuery object.
$ is a variable
name like any other (a, $b, a$b etc.) and it doesn't have any
special meaning like in PHP.
Knowing that we can take another look at our example:
var $f = function($) { return $*$; };
var jQuery = 2;
console.log( $f(jQuery) ); // Gives: 4
// An inline version (immediately invoked)
console.log( (function($) { return $*$; })(jQuery) ); // Gives: 4
Type 3, in order to work would have to look like this:
(function($){
//Attach this new method to jQuery
$.fn.extend({
//This is where you write your plugin's name
'pluginname': function(_options) {
// Put defaults inline, no need for another variable...
var options = $.extend({
'defaults': "go here..."
}, _options);
//Iterate over the current set of matched elements
return this.each(function() {
//code to be inserted here
});
}
});
})(jQuery);
I am unsure why someone would use extend over just directly setting the property in the jQuery prototype, it is doing the same exact thing only in more operations and more clutter.

Categories