I have written a jQuery plugin which I want to call a custom function on like so...
(function($) {
$.fn.testPlugin= function(options) {
var settings = {
func: null
};
if (options) {
$.extend(settings, options);
}
settings.func();
};
})(jQuery);
In this case I want to run the doSomething function.
$(document).ready(function(){
$('div').testPlugin({
func: 'doSomething'
});
});
function doSomething() {
alert('hello');
}
I always get the error settings.func is not a function so I am having to use:
eval(settings.func+"()");
Intead of:
settings.func();
Which is not ideal! Any ideas why I am getting this?
Because you're assigning a string to settings.func, not a function. Strings are never functions, even if they contain the name of a function.
Functions are first-class citizens, however, which means you can use them as you would any other variable, assigning them to variables or passing them as arguments to other functions. Change:
$('div').testPlugin({
func: 'doSomething'
});
to
$('div').testPlugin({
func: doSomething
});
and it should work.
Related
In the widget I'm trying to call a function from a property in the options
getThing: this._runFunc()
but I get an error saying _runFunc() is not an instance of an object? can you please help?
$.widget('my.testW', {
options:{
buttons:buttons,
getThing: this._runFunc() // why wont _runFunc work?
},
_create: function () {
//do things
var s = this.options.getThing;
},
_runFunc: function (){
return 'hello world'
}
});
In the $.widget call, the options object and the anonymous object literal within which it is contained are just parameters to $.widget, so this refers to whatever this was outside the $.widget call, and not the newly defined widget.
AFAIK, there's no way to refer to some other element of the same anonymous object literal from within values of that literal.
If you wish to hide your function, you could define your widget thus:
(function() {
function _runFunc() {
return 'hello world';
};
$.widget(..., {
options: {
getThing: _runFunc()
},
_runFunc: _runFunc; // if you want to expose this method
});
})();
where the IIFE encloses the utility function within that scope.
I see a lot of javascript code that passes a function as a parameter that returns an anonymous object.
myFunction(function() {
return {
foo: 'bar'
};
});
What is the advantage or the purpose of using this instead of simply passing directly an anonymous object?
myFunction({
foo: 'bar'
});
The difference is that if you alter the argument passed in your second code snippet, there is no way to get the original argument again.
If you pass an function instead you can call the function more than once and get always the same argument back. (if the function is implemented this way)
Furthermore if you use a function you can do additional stuff like logging how often your function / argument was called or so on. So using a function adds more flexibility for the user of the function.
For the developer of the function on the other hand accepting a function as argument can cause the tiny problem that a function doesn´t have to return the same value every time you call it - myFunc() == myFunc() COULD return false, therefore i would not recommend handing over a function if it is supposed to JUST return an argument.
Backbone uses have a lot of places where they will initialize the function if passed to get the value, eg.
Backbone.Model.extend({
url: function() { return 'myurl.aspx'; }
});
// VS
Backbone.Model.extend({
url: 'myurl.aspx'
});
This is clever if you will have to make some calculation / run some conditions before you'ill know that the url is.
Backbone.Model.extend({
url: function() {
if ( this.get('name') ) {
return 'service1.aspx';
}
else {
return 'service2.aspx';
}
}
});
Your first example sends an anonymous function as the first argument to myFunction while the second example sends an object as the first argument.
myFunction(function() {
return {
foo: 'bar'
};
}); // function() {...}
myFunction({
foo: 'bar'
}); // {foo: 'bar'}
function myFunction(what) {
console.log(what);
}
If you are talking about closures, the main difference is that you can have private variables inside closures:
var setGet = (function() {
var v = null;
return {
get: function() { return v; },
get: function(val) { v=val; },
};
});
// VS:
var setGet = {
v: null,
get: function() { return this.v; },
get: function(val) { this.v; },
};
In the first example you can't access the variable v without using .get/.set on setGet while in the 2. example i can simple change it by setting setGet.v = 'new_val';
In the first example You are passing a callback function.
When we pass a callback function as an argument to another function,
we are only passing the function definition. We are not executing the function
in the parameter.
And since the containing function has the callback function in its parameter as a function definition, it can execute the callback anytime. This allows us to execute the callback functions at any point in the containing function.
A simple example for this is jQuery click binding :
/The anonymous function is not being executed there in the parameter.
//The anonymous function is a callback function
$("#btn_1").click(function() {
alert("Btn 1 Clicked");
});
But in the second example you are simply passing an object to the called function.
Use this link to get more details about Callback functions. Enjoy :)
I think, it really depends where you saw the code being used.
In this case, myFunction seems to require you to pass a function rather than an Object.
But in general, Consider this
myFunction(function() {
var a = "bar";
return {
foo: a
};
});
and this:
var a = "bar"
myFunction({
foo: a
});
In the second case, anyone outside is able to access a. But in first case, a becomes similar to a private variable which is exposed as public by the function. So you might observe this in places where people wish to follow OOP concepts in the otherwise classless JS.
Another case is where you require a callback function or some function that is to be called later. So if the data is to be preserved until a certain something is over you can make it available as the return value of a function, rather than storing it globally...
Hi I have a few custom functions wrapped in jQuery's document.ready function. Most of these functions are utilized from within that function and work, but there is a case where I would like to access a function contained within this from the global scope. How can I do this? can i do something like:
jQueryReadyScope.myFunctionName('paramaters');
Thank you very much.
Nope, but you can name the function and pass it to .ready():
var myFunctionName = function (params) {
// do things
}
// pass as callback to ready function
jQuery(document).ready(myFunctionName);
// access directly like any other function:
myFunctionName('paramaters');
That's a scope issue, and all you need to do is specify the namespace. In this case, you're talking global so we'll use window.
window.myFunction = function() { ... stuff }
To access it from the global scope it would need to be assigned to a global variable, either by declaring it outside your document ready or by assigning it as a property of window:
var yourGlobalFunction1 = function() { ... }
$(document).ready(function() {
function privateFunction() { ... }
window.yourGlobalFunction2 = function() { ... };
yourGlobalFunction1();
privateFunction();
yourGlobalFunction2();
});
yourGlobalFunction1();
// and then at some later point AFTER the document ready has run,
// e.g., in response to some event:
$("#someelement").click(function() {
yourGlobalFunction2();
});
I'm learning to use object literals in JS, and I'm trying to get a function inside an object to run by calling it through another function in the same object. Why isn't the function "run" running when calling it from the function "init"?
var RunApp = {
init: function(){
this.run()
},
run: function() {
alert("It's running!");
}
};
That code is only a declaration. You need to actually call the function:
RunApp.init();
Demo: http://jsfiddle.net/mattball/s6MJ5/
There is nothing magical about the init property of an object, which you happen to have assigned a function to. So if you don't call it, then it won't run. No functions are ever executed for you when constructing an object literal like this.
As such, your code becomes this:
var RunApp = {
init: function(){
this.run()
},
run: function() {
alert("It's running!");
}
};
// Now we call init
RunApp.init();
You can try the following code. It should work:
var RunApp = {
init: function(){
RunApp.run()
},
run: function() {
alert("It's running!");
}
};
I'm trying to access a nested function by passing the function name in as a string and then calling it. Eg, see this post
function outer(action){
window["outer"][action]();
function inner(){
alert("hello");
}
}
outer("inner");
However it doesn't work. Error:
window.outer[action] is not a function
How to make this work, or an alternative way of calling a nested function.
The reason for this is that I am trying to hide a bunch of functions that are called by an iframe inside a functions scope.
function outer(action){
var inner = {
func1: function() {},
func2: function() {},
func3: function() {},
// ...
}
inner[action]();
}
outer("func1");
In that way you are trying to access the "inner" property of the "outer" function (outer.inner) that is not defined. The only way to do that is by using eval:
function outer(action){
eval(action+"()");
function inner(){
alert("hello");
}
}
outer("inner");
But remember eval is evil is some situations so be careful.