I want to pass an object array to the setTimer function in Javascript.
setTimer("foo(object_array)",1000);
am getting error on this code.
**Note:**Sorry ! some correction in my question : Is it possible in setInterval() function.
Use an anonymous function instead of a string on the first parameter of the setTimeout or setInterval functions:
// assuming that object_array is available on this scope
setInterval(function () { foo(object_array); }, 1000);
Why it works:
When you define an inner function, it can refer to the variables present in their
outer enclosing function even after their parent functions have already terminated.
This language feature is called closures.
If you pass a string as the first argument of these functions, the code will be executed internally using a call to the eval function, and doing this is not considered as a good practice.
Eval provides direct access to the JavaScript compiler and executes the code it's passed with the privileges of the caller, also using eval repeatedly/extensively (i.e. your setInterval function is a good example) will lead to performance issues.
I'm going to expand on Luke's answer here because it addresses a use case that CMS's (and most answers to this kind of question) does not.
If you need to bind your arguments to the function call at the time you set the timeout, a simple function enclosure will not work:
echo = function (txt) { console.log(txt); };
val = "immediate A";
echo(val);
val = "delayed";
window.setTimeout(function () { echo(val); }, 1000);
val = "immediate B";
echo(val);
Assuming you are using Firebug's console, the above will output "immediate A", "immediate B" and then "immediate B" 1 second later. To bind the value at the time of the setTimeout call use Luke's trap method. The following modifies it a little to accept arbitrary functions and argument lengths:
echo = function (txt) { console.log(txt); };
trap = function (fn, args) {
return function() {
return fn.apply(this, args);
};
};
val = "immediate A";
echo(val);
val = "delayed";
window.setTimeout( trap(echo, [val]), 1000);
val = "immediate B";
echo(val);
Not sure if there is a way to pass the caller's context in implicitly, but it could be further expanded to accept a context argument if "this" doesn't get you there.
first, it's 'setTimeout'
second, don't pass a string. The real solution depends on the rest of the code. Most robust way would be to trap the scope:
var obj_array = something;
function trap(obj)
{
function exec() { foo(obj); }
return exec;
}
setTimeout(trap(obj_array), 1000);
trap returns a function that has your array trapped in its scope. This is a generic function but to make it specific to your problem, it can be simplified:
var obj_array = something;
function trap()
{
function exec() { foo(obj_array); }
return exec;
}
setTimeout(trap(), 1000);
or even:
var obj_array = something;
function trap()
{
foo(obj_array);
}
setTimeout(trap, 1000);
and finally condensed down to:
var obj_array = something;
setTimeout(function() { foo(object_array); }, 1000);
EDIT:
My functions (or at least 1 iteration of them I found in a backup here)
Function.prototype.createDelegate = function(inst, args) {
var me = this;
var delegate = function() { me.apply(inst, arguments); }
return args ? delegate.createAutoDelegate.apply(delegate,args) : delegate;
};
Function.prototype.createAutoDelegate = function() {
var args = arguments;
var me = this;
return function() { me.apply({}, args); }
};
GIVEN:
function test(a, b) { alert(a + b); }
USAGE:
setTimeout(test.createAutoDelegate(1, 2), 1000);
OR GIVEN:
var o = { a:1, go : function(b) { alert(b + this.a); }}
USAGE:
setTimeout(o.go.createDelegate(o,[5]), 1000);
//or
setTimeout(o.go.createDelegate(o).createAutoDelegate(5), 1000);
Related
I saw this shortcut given as an answer on a code Kata but I am having difficulty understanding exactly what the below example is doing.
function func(fn) {
return fn.bind.apply(fn, arguments);
}
So far my understanding is that bind creates a new function similar to doing the following:
function func(fn) {
return function () {
return fn.apply(fn, arguments);
};
}
Is this the case? Any clearer answers or breakdowns of what is going on would be great.
fn.bind
is just
Function.prototype.bind
So we're applying bind to fn, returning
fn.bind(arguments[0]/* doesn't matter, it's fn*/, arguments[1], arguments[2], etc.)
So the bound function is called with arguments being the arguments of func after fn.
Another way to write it would have been:
function func(fn) {
var args = [].slice.call(arguments, 1);
return function () {
var localArgs = [].slice.call(arguments);
return fn.apply(fn, args.concat(localArgs));
};
}
The fact that the context of the call is the initial function (arguments[0]) is most certainly only a side effect. The important thing is we wrap the arguments with the function, but make it possible to dynamically pass other arguments.
Example 1, wrapping all arguments :
function add(a,b){
return a+b
}
var f = func(add, 2 ,3); // f is a function which will always apply add to 2 and 3
console.log(f()) // logs 5
Exemple 2, currying:
function multiply(a,b){
return a*b
}
var multBy2 = func(multiply, 2);
console.log(multBy2(3)) // logs 6
Basically I want to do this:
someFunction() // do something
someFunction.somePropertyFunction()
someFunction() // Now someFunction is modified; it should now exhibit a different behaviour
Is this possible?
EDIT:
I'm not looking for what #Kolink was suggesting. Basically I want to augment a function's functionality by calling one of it's property function.
Specifically, I need to: 1. have access to the original function inside my property function (which is entirely doable using this), and 2. bind a new function to the original function's name (which I'm not sure if it's possible).
Just to be clear, I don't have access to the internal definition of the function that I want to augment. I want to attach a function to Function.prototype (so that it will be available as a property of the function that I want to augment), and then I will call func.augmentThis(), and then func should be augmented. But I'm not sure how, hence the question :P
Easily. Here's an example:
var derp = 123;
someFunction = function() {alert(derp);};
someFunction.somePropertyFunction = function() {derp = 456;};
someFunction(); // alerts 123
someFunction.somePropertyFunction();
someFunction(); // alerts 456
Okay, that's an oversimplified example, but yeah, it's entirely possible.
If your question is whether a function attached as a property to another function has a way to access the function to which it is attached, the answer is no. After all, the same function could be attached to any number of functions of objects.
So one alternative is to explicitly refer to the "mother" function within the function that is attached to it and intended to change its behavior:
function f (n) { alert (n + f.offset); }
f.offset = 0;
f.change_offset = function (i) { f.offset = i; };
f (1); //1
f.change_offset (100);
f (1); //101
Here, f is hard-wired into the definition of change_offset. If this bothers you, or you want something slightly more general, write a little routine to set a function as a property on another function, while binding its this to the function being attached to:
function set_func_as_func_prop ( propname, func_to_set, func_to_set_on ) {
func_to_set_on[propname] = func_to_set.bind(func_to_set_on);
}
Now you can write the function more generally
function change_offset (i) {
this.offset = i;
}
and set it on f or any other function.
set_func_as_func_prop ("change_offset", change_offset, f);
set_func_as_func_prop ("change_offset", change_offset, g);
Sort of:
function someFunction() {
return realFunction.apply(this, arguments);
}
function someFunctionA(name) {
return 'Hello, ' + name + '!';
}
function someFunctionB(name) {
return 'Goodbye, ' + name + '...';
}
var realFunction = someFunctionA;
someFunction.somePropertyFunction = function () {
realFunction = someFunctionB;
};
Sure it's possible. It's not recommended, but it's possible. For example:
function a() {
alert("a");
}
function b() {
alert("b");
}
function c() {
return c.f.apply(this, arguments);
}
c.f = a;
c.toggle = function () {
c.f = c.f === a ? b : a;
};
Now let's test it:
c(); // alerts "a"
c.toggle();
c(); // alerts "b"
See the demo: http://jsfiddle.net/LwKM3/
I want to attach a function to Function.prototype. Then I need to bind a new function to the original function's name (which I'm not sure if it's possible).
That indeed is impossible, you don't know what refers to the function. And you cannot change the internal representation of a function, which is immutable.
The only thing you can do is to create a new function and return that, to let the caller of your method use it somehow - specifically assigning it to the original variable:
somefunction = somefunction.augmentSomehow();
Your method for that will look like this:
Function.prototype.augmentSomehow = function() {
var origFn = this;
return function() {
// in here, do something special
// which might include invoking origFn() in a different way
};
};
Not sure if this helps, but I would implement described problem in following way:
// defined by somebody else - unknown to developer
var someFunction = function() {
alert("this is initial behavior");
}
someFunction(); // returns "this is initial behavior"
// defines parent object on which someFunction() is called
var parentObject = this; // returns window object (as called direclty in the
// browser)
// if you are calling someFunction from some object (object.someFunction())
// it would be:
// var parentObject = object;
// augumentThis definition
someFunction.augumentThis = function() {
var newFunction = function() {
alert("this is changed behavior");
};
parentObject.someFunction.somePropertyFunction = function() {
parentObject.someFunction = newFunction;
parentObject.someFunction();
};
};
someFunction.augumentThis(); // change function behavior
someFunction(); // "this is initial behavior"
someFunction.somePropertyFunction(); // "this is changed behavior"
someFunction(); // "this is changed behavior"
so a simple example would be
function a() {
alert("something");
}
anything.onclick = a; // this is without parentheses
anything.onclick = a(); // this is with parentheses
What is the difference between the two?
And one thing more: if I define the same function but this time return false, will it work?
function a(){
alert("something");
return false;
}
The difference is that a() calls the function while a is the function.
console.log( a() ); // false
console.log( a ); // function() {...}
To make it clear what technically happens when you use the second part of your example, let's redefine alike this:
a = function() {
return 100;
};
and set the event handler:
anything.onclick = a();
f() not only calls the function f but returns its return value. So when setting a variable or object property to a function call, the return value of the function call will be assigned. So the above statement is effectlively equivalent to:
anything.onclick = 100;
which doesn't make sense and might cause an error. If a function doesn't have a return value, its return value is implicitly undefined.
However, if you had set a variable equal to a without calling it, it would be the same as setting a regular function expression to that variable:
var a = function() { ... },
b = a; // b = function() { ... }
b would perform the same operation as a would.
So in your example go with the first one because it makes sense! The only case in which you would assign the return value of the function call to an event handler is if the function returns another function. For instance:
var x = function(xyz) {
return function() {
console.log(xyz);
};
};
anything.onclick = x("Hello World"); // = function() {
// console.log("Hello World");
// }
Assigns reference:
anything.onclick = a; //assigns a reference
With your function it is:
anything.onclick = function() {
alert("something");
}
Executes method and assigns the returned result
anything.onclick = a(); //calls the method and assigns whatever is returned.
With your function it is:
anything.onclick = false;
The parenthesis at the end of the function is the permission for javascript engine to execute the function. If you don't supply it, it won't be executed at all.
If you do x=a() you are invoking the function but if you do x=a you are passing a pointer to a function
long story short:
Let's say we have
function f(){} or f = function(){}
If you now write
someFunction(f());
it will call f() and whatever f() returns will be passed as argument to someFunction().
If you write
someFunction(f);
on the other hand (when defined like the latter), f will be passed to someFunction() as (a variable holding) the function.
This could be used e.g. if the function is supposed to be used later on but maybe can't be called some other ('normal') way.
( Of course, depending on language, "function" could obviously be a "method" and the language could not even have function-variables or however you call it! )
( off topic: note that this answer says the same as the other answers because that is THE true answer but I did not want to edit the other answers because each may be found differently helpful by different people )
I am trying to use setTimeout() inside a class function in JavaScript. The setTimeout() is supposed to trigger another method in the same Class, so the function I am passing it is written as window.setTimeout("this.anotherMethod", 4000). That bring the problem: this references the calling Object, in the case of setTimeout() it is window. How can I use enclosures to return a reference to the Class Object itself?
myObject = function(){
this.move = function(){
alert(this + " is running");
}
this.turn = function(){
alert(this + " is turning");
}
this.wait = function(){
window.setTimeout("this.run" ,(1000 * randomNumber(1,5)));
}
this.run = function(){
switch(randomNumber(0,2)){
case 0:
this.move();
break;
case 1:
this.turn();
break;
case 2:
this.wait();
}
}
}
You can do this:
var that = this;
setTimeout(function () {
that.doStuff();
}, 4000);
You can also bind for more succinct code (as originally pointed out by #Raynos):
setTimeout(this.doStuff.bind(this), 4000);
bind is a standard library function for exactly this coding pattern (ie capturing this lexically).
You can also bind a function to scope.
setTimeout(this.run.bind(this) ,(1000 * randomNumber(1,5)));
Be warned Function.prototype.bind is ES5
this can be problematic in javascript, as you've discovered.
I usually work around this by aliasing this inside the object so that I can use the alias whenever I need a reference back to the containing object.
MyObject = function ()
{
var self = this;
// The rest of the code goes here
self.wait = function(){
window.setTimeout(self.run ,(1000 * randomNumber(1,5)));
}
}
this.wait = function(){
var self = this;
window.setTimeout(function() { self.run() } ,(1000 * randomNumber(1,5)));
}
So you store the reference to the object you're calling .run on in a local variable ('self').
class A{
setTimeout(()=>{
// here this != undefined because of arrow function
},500);
}
this is sensitive to the context in which it is called. When you pass a string to setTimeout then that is evaled in a completely different context.
You need to preserve the current value of this (by copying it to a different variable) and maintain the scope (by not using (implied) eval).
this.wait = function(){
var self = this;
setTimeout(function () { self.run() },
(1000 * randomNumber(1,5))
);
}
At the top of your main myObject make a new reference to the current value of this:
var self = this;
and then create a closure for your timer callback that uses that new reference instead of the global object that setTimeout will use as the default context in callbacks:
setTimeout(function() {
self.run();
}, 4000);
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
inside func, this always refer to the global object. you can pass in the current object into func,
var timeoutID = window.setTimeout(func, delay, this);
function func(that) {...}
unfortunately it does NOT work in IE
Note that passing additional parameters to the function in the first syntax does not work in Internet Explorer.
you can just use the arrow function syntax:
setTimeout(() => {
this.doStuff();
}, 4000);
Have you tried;
window.setTimeout("myObject.run" ,(1000 * randomNumber(1,5)));
You can use this code instead, which works in all modern browsers -
setTimeout(function(thisObj) {thisObj.run();},1000,this);
Ref: http://klevo.sk/javascript/javascripts-settimeout-and-how-to-use-it-with-your-methods/
Shorter way. Without anonymous func.
var self = this;
setTimeout(self.method, 1000);
It is not recommended to use setTimeout or setInterval using strings
setTimeout("myFunction()", 5000);
//this is the same as
setTimeout(function(){ eval("myFunction()"); }, 5000)); //<-- eval == BAD
Ran into a more complex situation...class A has a member of type B and a method that calls setTimeout which calls a method on class B. Solved as follows:
class A {
constructor(b) {
this.b = b;
}
setTimer(interval) {
setTimeout(this.b.tick.bind(this.b), interval);
}
}
class B {
constructor(name){
this.name = name;
this.ele = window.document.getElementById('B');
}
tick() {
console.log(this);
this.ele.innerText += ' ' + this.name;
}
}
Which bound A.b to this within B.tick and worked.
Here's a fiddle with bind: https://jsfiddle.net/jrme9hyh/
And one without bind which fails: https://jsfiddle.net/2jde8tq3/
to call a function at the same time it's defined, i had been using:
var newfunc = function() {
alert('hi');
};
newfunc();
is the following the correct way of combining these 2:
var newfunc = function() {
alert('hi');
}();
There could be a number of reasons you wish to do this. I'm not sure what yours are, but let me introduce a couple of favourite patterns:
Pattern #1: A singleton. The function is executed and then becomes a singleton object for use by other components of your code.
var singletonObject = new function() {
// example private variables and functions
var variable1 = {};
var variable2 = {};
var privateFunction = function() {
};
// example public functions
this.getData = function() {
return privateFunction(variable1, variable2);
};
// example initialisation code that will only run once
variable1.isInitialised = true;
};
Pattern #2: Self-executing anonymous function ... handy for sooo many reasons!
// Declare an anonymous function body.
// Wrap it in parenthesis to make it an "expression.
// Execute it by adding "();"
(function(){})();
And here's an example that also creates a namespace for your objects.
I'm using "NS" as an example namespace:
// declare the anonymous function, this time passing in some parameters
(function($, NS) {
// do whatever you like here
// execute the function, passing in the required parameters.
// note that the "NS" namespace is created if it doesn't already exist
})(jQuery, (window.NS = window.NS || {}));
You can also set the context of a self-executing function by using .call or .apply instead of the usual parenthesis, like this:
(function($){
// 'this' now refers to the window.NS object
}).call(window.NS = window.NS || {}, jQuery);
or
(function($){
// 'this' now refers to the window.NS object
}).apply(window.NS = window.NS || {}, [jQuery]);
var newfunc = function f() {
alert("hi!");
return f;
}();
Having a named function expressions allows the function to recursively call itself or, in this case, return itself. This function will always return itself, however, which might be an annoyance.
No. Your second example will immediately call the anonymous function and assign its return value to newfunc.
adamse describes an approach which appears to work. I'd still avoid the approach as the two step process is easier to read and thus will be easier to maintain.
If I understand your question correctly, give this a try:
(f = function (msg) {
msg = msg ? msg : 'default value';
alert(msg); }
)();
f('I\'m not the default value!');
You'll get two alerts, the first one will say "default value" and the second will say "I'm not the default value. You can see it in action at jsBin. Click 'preview' to make it run.
you could do like this:
o = {};
o.newfunc = ( function() {
function f() {
alert('hi');
}
f();
return {
f : f
};
}
)();
then calling the function like:
o.newfunc.f();
will also render an alert message