I have next function
var hideAll = function() {
// code
return ///...
};
And I am using this function like callback in another function.
When I am using it like
function (params, hideAll) {}
all working well, but when I am using
function (params, hideAll() ) {}
all not working well!
So my question is, what is difference between hideAll and hideAll() function executions?
hideAll - this is a reference to the function
hideAll() - this is execution of the function, its result
function (params, hideAll) {} is a correct function definition,
whereas function (params, hideAll() ) {} is not - you are unable to call another function in function definition.
However you could still write the following valid code:
var hideAll = function() {
// code
return ///...
};
var functionWithCallback = function(callback){
callback();
}
var closureReferringHideAll = function(){
hideAll();
}
// The following two lines will do exactly the same in current context,
// i.e. execute hideAll.
functionWithCallback(hideAll);
closureReferringHideAll();
hideAll() is not a function, it is result of execution function.
function hideAll(){
return 0;
}
hideAll() - number 0
hideAll - function
In Javascript and in many other languages functions are "first class objects" and this means that you can call/execute a function but you can also store the function in a variable or in an array, or you can pass a function to another function.
Note that I'm not talking about passing the value resulting from calling a function... but the function itself. Consider:
function test10(f) {
for (var i=0; i<10; i++)
alert(f(i));
}
function square(x) { return x*x*; }
function cube(x) { return x*x*x; }
test10(square);
test10(cube);
The last two lines are passing a function (square and cube) as a parameter to function test10.
The () syntax tells Javascript that you want to make the call, and can be used not only with function names, but with any expression like variables or array elements... for example:
var f_arr = [square, cube];
for (var i=0; i<2; i++)
alert(f_arr[i](i+42)); // Will call square(42) and cube(43)
Actually in Javascript the code
function square(x) {
return x * x;
}
is not identical but similar to
square = function(x) {
return x * x;
};
so defining a function is indeed close to assigning a variable
Let's step back for a moment and assume you would call a method foo
first like this:
foo(params, hideAll() ) {}
This uses the return value of hideAll as the value
whereas
foo(params, hideAll) {}
Uses the hideAll function itself as the value
However, what you actually tried to do is to declare a function like this:
function (params, hideAll() ) {}
That makes no sense. You can't declare a function with anything different from a parameter in the parameter list.
So while both forms are legal for function invocation (still with a total different meaning) the latter isn't legal for function declaration
Related
I am having trouble passing a kata. I believe I am on the right track, but do not fully understand how to retrieve the desired results.
The Instructions
Write a method that takes in a function and the arguments to the function and returns another function which when invoked, returns the result of the original function invoked with the supplied arguments.
Example Given
Given a function add
function add (a, b) {
return a + b;
}
One could make it lazy as:
var lazy_value = make_lazy(add, 2, 3);
The expression does not get evaluated at the moment, but only when you invoke lazy_value as:
lazy_value() => 5
Here is my half a day endeavor conclusion
var make_lazy = function () {
var innerFunction = null;
var array = [];
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] == 'function') {
innerFunction = arguments[i];
} else {
array.push(arguments[i]);
}
}
innerFunction.apply(innerFunction, array);
innerFunction();
};
I'm using arguments and apply() and think I am close? However I am getting TypeError: lazy_sum is not a function at Object.exports.runInThisContext within test results. Any help, especially understanding what is going on, is appreciated. Thanks
...
return function() {
return innerFunction.apply(this, array);
};
};
Thanks again all. Problem solved.
I have three functions that I have listed in an array. Now I need a random function of the three to be called when pressing a button. However, when I press the button it calls all three functions and I'm not quite sure where I've gone wrong. It looks like this right now:
function Arm1function1(){
this.parent.parent.parent.Armfront1.visible = true;
this.parent.parent.parent.Armback1.visible = false;
}
function Arm1function2(){
this.parent.parent.parent.Armfront1.visible = false;
this.parent.parent.parent.Armback1.visible = true;
}
function Arm1function3(){
this.parent.parent.parent.Armfront1.visible = false;
this.parent.parent.parent.Armback1.visible = false;
}
function getRandomElementOf(Armbuttonarray1:Array):Object {
var Armbuttonarray1:Array = [Arm1function1(), Arm1function2(), Arm1function3()];
var idx:int=Math.floor(Math.random() * Armbuttonarray1.length);
return Armbuttonarray1[idx];
}
Randombutton1part1.addEventListener(MouseEvent.CLICK, Randombutton1part1Click);
function Randombutton1part1Click(e:MouseEvent):void
{
getRandomElementOf(null);
}
Any clue of where I've gone wrong?
Your issue is this line:
var Armbuttonarray1:Array = [Arm1function1(), Arm1function2(), Arm1function3()];
When populating that array, you are actually populating it with the results of the functions.
Should be:
var Armbuttonarray1:Array = [Arm1function1, Arm1function2, Arm1function3];
Notice the lack of parenthesis ().
You want to actually execute the function on the click handler, so you'll need to tweak that a bit too:
getRandomElementOf(null)();
or
getRandomElementOf(null).call();
As an aside, your getRandomElementOf function should probably look more like this:
function getRandomElementOf(array:Array):Object {
return array[Math.floor(Math.random() * array.length)];
}
Then do:
getRandomElementOf([Arm1function1, Arm1function2, Arm1function3])();
I'm attempting to gradually refactor existing code. I have a set of functions that are defined, and only differ by one of the internal arguments:
function loadGame1():void
{
loadGame("save1");
}
function loadGame2():void
{
loadGame("save2");
}
function loadGame3():void
{
loadGame("save3");
}
//... snip many, many lines
// Note- I cannot pass function arguments at this time!
picker(loadGame1, loadGame2, loadGame3 ...);
I'm trying to refactor at least part of this (I can't completely replace the whole thing yet, too many interdependencies).
Basically, I want to be able to generate a big set of functions with the difference between the functions being a internal parameter:
var fNames:Array = new Array("save1", "save2", "save3");
var funcs:Array = new Array();
for (var i = 0; i < fNames.length; i += 1)
{
trace("Creating function with indice = ", i);
funcs.push(
function() : void
{
saveGame(fNames[i]);
}
)
}
picker(funcs[0], funcs[1], funcs[2] ...);
However, as I understand it, closure is causing the state of i to be maintained beyond the scope of the for loop, and any attempt to call any of the generated functions is failing with an out-of-bounds error, which is what you would expect given that i will reach fNames.size + 1 before i < fNames.size evaluates to false.
So, basically, given that I need to generate functions that are passed as arguments to a pre-existing function that I cannot change currently. How can I dynamically generate these functions?
Try to use IIFE:
for (var i = 0; i < fNames.length; i += 1)
{
(function(i){
trace("Creating function with indice = ", i);
funcs.push(
function() : void
{
saveGame(fNames[i]);
}
)
})(i);
}
Let's say I have a series of animations that I want to execute in sequence. If I do it like this, am I creating a huge call stack that eats up more memory than necessary?
function ch1():void {
var someVar:uint;
function doThis();
...
...
ch2();
}
function ch2():void {
var someOtherVar:String;
function doThat();
...
...
ch3();
}
function ch3():void {
var evenMoreVar:Number;
function doMore();
...
...
ch4();
}
Would it be better to call the next function by doing something like this to avoid a huge call stack?
function ch1():void {
addEventListener("ch1_end",ch2);
var someVar:uint;
function doThis();
...
...
dispatchEvent(new Event("ch1_end"));
}
Using events is a better way to deal with sequences like yours, but in some simple cases you can just delay each call a little so you can be sure they will not run in the same time and cause freezing your swf , try to use something simple like setTimeout and see the results, if it is not good then you should try useing the events as you have described in your question .
var nextCallDelay:Number = 20; // in milliseconds, change it to fit your needs
function ch1():void {
var someVar:uint;
function doThis();
...
...
setTimeout(ch2, nextCallDelay);
}
function ch2():void {
var someOtherVar:String;
function doThat();
...
...
setTimeout(ch3, nextCallDelay);
}
function ch3():void {
var evenMoreVar:Number;
function doMore();
...
...
setTimeout(ch4, nextCallDelay);
}
How about you return something instead so you don't have that huge stack of interconnected functions ?
function ch1():void {
return true
}
function ch2():void {
return true
}
function myAnim(){
var ani1 = ch1();
var ani2 = ch2();
}
Hai am Getting trouble to retrive the values from function(addText).i Called from another function onFullScreen().I dont know how Can i do this,Kindly Help me?Here i attach my Code
private function addText()
{
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, ncOnStatus);
function ncOnStatus(infoObject:NetStatusEvent)
{
trace("nc: "+infoObject.info.code+" ("+infoObject.info.description+")");
if (infoObject.info.code == "NetConnection.Connect.Success")
{
initSharedObject(chatSharedObjectName);
}
}
function formatMessage(chatData:Object)
{
trace("room"+chatData.message);
number = chatData.txtalign;//i want to retrive the value of number
number.toString();
return number;
}
function syncEventHandler(ev:SyncEvent)
{
var infoObj:Object = ev.changeList;
// if first time only show last 4 messages in the list
if (lastChatId == 0)
{
lastChatId = Number(textchat_so.data["lastChatId"]) - 1;
if (lastChatId < 0)
lastChatId = 0;
}
}
function connectSharedObject(soName:String)
{
textchat_so = SharedObject.getRemote(soName, nc.uri)
// add new message to the chat box as they come in
textchat_so.addEventListener(SyncEvent.SYNC, syncEventHandler)
textchat_so.connect(nc)
}
function connectSharedObjectRes(soName:String)
{
connectSharedObject(soName)
trace(soName)
}
function initSharedObject(soName:String)
{
// initialize the shared object server side
nc.call("initSharedObject", new Responder(connectSharedObjectRes), soName)
}
}
i using the variable in another function ,but I cannot retrive the Value.
private function onFullScreen(event:FullScreenEvent):void
{
mediaContainer.addMediaElement(alert);
alert.alert("Error",number);// if i cannot retrive the value hnumber here
}
The addText() method is asynchronous, meaning that you can't simply call it , you need to wait for the event listener to return a value.
I'm not sure why you would feel the need to enclose all these functions, it's not very legible and I doubt it's necessary. You're also missing quite a few semi colons...
In any case , I couldn't see where the formatMessage() method was called, it seems that's the only place where the "number" variable gets defined.
You could create a variable outside the scope of the functions.
private var num:int;
Then in your addText function, assign a value to the variable:
num = infoObject.info.code;
Then in your onFullScreen function, access the num variable:
alert.alert("Error", num);