Google

Jan 11, 2012

JavaScript Interview Questions and Answers: Function.call, Function.apply, and Callback functions



Q. What are the different ways to invoke a function? What would the implicit reference "this" refer to?
A. The functions can be invoked via one of the following 5 ways

  1. function_name(param1, param2, etc); --> "this" refers to global object like window.
  2. obj1.function_name(param1,param2,etc);  --> "this" refers to obj1.
  3. The constructor.
  4. function_name.call(objRef, param1);    //remember that the functions in JavaScript is like an object and it has it's own methods like toString(..), call(...), apply(...), etc.
  5. function_name.apply(objRef, params[parama1,param2, etc]);


So, why use  function_name.call(...) or function_name.apply( ... ) as opposed to just function_name( ... )? Let's look at this with some examples.
var x = 1;           //global variable x;

var obj1 = {x:3};   //obj1 variable x
var obj2 = {x:9};   //obj2 variable x

function function_name(message) {
   alert(message + this.x) ;
}


function_name("The number is ");              //alerts the global x --> The number is 1

//the first argument is the obj reference on which to invoke the function, and the
//the second argument is the argument to the function call
function_name.call(obj1, "The number is ");   //alerts the obj1's x --> The number is 3
function_name.call(obj2, "The number is ");   //alerts the obj2's x --> The number is 5



//the first argument is the obj reference on which to invoke the function, and
//the second argument is the argument to the function call as an array
function_name.apply(obj1, ["The number is "]);   //alerts the obj1's x --> The number is 3
function_name.apply(obj2, ["The number is "]);   //alerts the obj2's x --> The number is 5


The purpose is of call and apply methods are  to invoke the function for any object without being bound to an instance of the this object. In the above example, the this object is the global object with the x value of 1.   In a function called directly without an explicit owner object, like function_name(), causes the value of this to be the default object (window in the browser). The call and apply methods allow you to pass your own object to be used as the "this" reference. In the above example, the obj1 and obj2 were used as "this" reference.



Q. What will be the alerted message for buttons 1-5 shown below?

The test.html stored under js_tutorial/html


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>
</head>
<body>
    <form id="someform">
       <input id="btn1" type="button" value="click-me1"/>  
       <input id="btn2" type="button" value="click-me2"/> 
       <input id="btn3" type="button" value="click-me3" onclick="buttonClicked()"/>  
       <input id="btn4" type="button" value="click-me4"/>  
       <input id="btn5" type="button" value="click-me5"/>  
    </form>
    
    <script language="javascript" type="text/javascript" src="../js/test.js">
    </script>
    
</body>
</html>


The test.js stored under js_tutorial/js.

function buttonClicked(){  
    var text = (this === window) ? 'window' : this.id;  
    alert( text );  
}  

var button1 = document.getElementById('btn1');  
var button2 = document.getElementById('btn2');  
var button4 = document.getElementById('btn4');  
var button5 = document.getElementById('btn5');  

button1.onclick = this.buttonClicked; //or just  button1.onclick = buttonClicked; 
button2.onclick = function(){   
 buttonClicked();   
};  

button4.onclick =  function(){   
 buttonClicked.call(button4);   
};  

button5.onclick =  function(){   
 buttonClicked.apply(button5);   
}; 


A. The "this" object passed to the buttonClicked function are as follows:

click-me1 --> btn1 ("btn1" because it's a method invocation and this will be assigned the owner object - the button input element)
click-me2 --> window (This is the same thing as when we assign the event handler directly in the element's tag as in click-me3 button)
click-me3 --> window (global object)
click-me4 --> btn4
click-me5 --> btn5

When defining event handlers via frameworks like jQuery, the library will take care of overriding the value of "this" reference to ensure that it contains a reference to the source of the event element. For example,


$('#btn1').click( function() {  
     var text = (this === window) ? 'window' : this.id;  //// jQuery ensures 'this' will be the btn1
    alert( text );  
});  


The jQuery makes use of apply( ) and call( ) method calls to achieve this.


Q. What will be the output for the following code snippet?

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>
</head>
<body>
    <form id="someform">
       <input id="btn1" type="button" value="click-me1" onclick="test()"/>  
    </form>
    
    <script language="javascript" type="text/javascript" src="../js/test2.js">
    </script>
    
</body>
</html>


the test2.js file.

var myobj1 = {  
  x:9, 
  myfunction:function(){
 
    if(this === window) 
     alert("x is not Defined");
 else if (this === myobj1)
     alert(this.x);
 else 
  alert("Error!");
  }
}


function test(){
 setTimeout(myobj1.myfunction, 1000);
}



A. The output in the alert will be "x is not defined". This is because the "this" will be referring to the default global object -- window. The above code can be fixed by replacing the test() function as shown below.

function test(){
 setTimeout(function(){
  myobj1.myfunction()}, 
 1000); 
}


Note: The setTimeout(..,..) method alerts only after 1 second of clicking the button.

Q. What is a callback function? Why would you need callback functions?
A. As mentioned earlier, the functions in JavaScript are actually objects. For example,

var functionAdd = new Function("arg1", "arg2", "return arg1 * arg2;");
functionAdd(5,9);  // returns 14
functionAdd(2,3);  // returns 5


So, the functions can be passed as arguments to other functions and invoked from other functions. For example,

function functionAdd(arg1, arg2, callback) {
  var result = arg1 + arg2 
  // Since we're done, let's call the callback function and pass the result
  callback(result);
}

 
// call the function
functionAdd(5, 15, function(result) {
    // this anonymous function will run when the callback is called
 console.log("callback called! " + result);
}); 


Why invoke the callback function when the functionAdd(..) could have executed the results? Client-side is predominantly asynchronous with following types of events.

UI Events like mouse click, on focus, value change, etc. These events are asynchronous because you don't know when a user is going to click on a button. So, callback functions need to be invoked when a button is clicked. For example JavaScript frameworks like jQuery quite often uses callback functions. Whether handling an event, iterating a collection of nodes, animating an image, or applying a dynamic filter, callbacks are used to invoke your custom code at the appropriate time.

The test.js.

$(document).ready(function(){
  $("button").click(function(){
    $("p").hide(2000,function(){
    console.log("Inside the callback function...");
   //called 2 seconds after the paragraph is hidden 
      alert("The paragraph is now hidden");
    });
  });
});


The test.html

<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="test.js"></script>

</head>
<body>
<button>Hide</button>
<p>The praragraph to hide when a button is clicked.</p>
</body>
</html> 


Timer functions like setTimeout(function, delay), setInterval(function, delay), etc will delay the execution of a function. For example, you might want to disable a form button after it's been clicked to prevent double form submission, but then re-enable it again after a few seconds. The clearTimeout() function then allows you to cancel the callback from occuring if some other action is done which means the timeout is no longer required.
Another reason why these timers are useful is for some repetitive tasks some milliseconds apartment. The reason why the timers are used instead of a simply while (true) { ... } loop is because Javascript is a single-threaded language. So if you tie up the interpreter by executing one piece of code over and over, nothing else in the browser gets a chance to run. So, these timers allow other queued up events or functions to be executed.

Invoke myObj1.myObj1.myMethod() after 1 second.

var myObj1 = {
     myVar:12, 
  myMethod:function(){
      alert(this.x || "Not defined") ; // "Not defined" is the default if x is not defined
    }
}


setTimeout(function(){myObj1.myMethod()}, 1000);




Ajax calls are made asynchronously and when a response is received from the server, a callback method is invoked to process the response. The Ajax calls do have the following states

AJAX states:

0: The request is uninitialized (before you've called open()).
1: The request is set up, but not sent (before you've called send()).
2: The request was sent and is in process (you can usually get content headers from the response at this point).
3: The request is in process; often some partial data is available from the response, but the server isn't finished with its response.
4: The response is complete; you can get the server's response and use it.

So, you want the callback function to be invoked when the state == 4. Let's look at an example.

Here is the test2.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script language="javascript" type="text/javascript" src="ajax.js">
</script>

<title>Insert title here</title>
</head>
<body>
</body>
</html>


The ajax.js.

function processAjaxRequest(url, callback) {
    var httpRequest; // create our XMLHttpRequest object
    if (window.XMLHttpRequest) {
     //For most browsers
        httpRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        //For IE
        httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    }

    //onreadystatechange event registers an anonymous (i.e. no name) function
    httpRequest.onreadystatechange = function() {
       // this is called on every state change
       if (httpRequest.readyState === 4) {
            callback.call(httpRequest.responseXML);   // call the callback function
       }
    };
    httpRequest.open('GET', url);
    httpRequest.send();
}


processAjaxRequest ("http://localhost:8000/simple", function() {
    console.log("Executing callaback function....");
    console.log("1.This will be printed when the ajax response is complete. ");   //LINE A
});

console.log("2. This will be printed before the above console.log in LINE A.");   //LINE B


Note: If you use FireFox, you can vie the console via Tools --> Web Developer --> Web Console. When you run the above example, check the web console output.

Now, for the purpse of learning JavaScript, Ajax, etc, you can create your own HTTP server with a quick and dirty approach as shown below. The Java 6, has a built in non-public API for HTTP. This approach should not be used in real life.

The Java HTTP Server

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;



public class SimpleJavaHTTPServer {

 public static void main(String[] args) throws Exception {
  HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
  server.createContext("/simple", new MyHandler());
  server.setExecutor(null); // creates a default executor
  server.start();
 }

 static class MyHandler implements HttpHandler {
  public void handle(HttpExchange t) throws IOException {
   String response = "<ajax-xml>some text</ajax-xml>";
   t.sendResponseHeaders(200, response.length());
   OutputStream os = t.getResponseBody();
   os.write(response.getBytes());
   os.close();
  }
 }
}


The LINE B will be printed before LINEA.

Note: If you run the above Java code within Java 6 or later, you will get an ajax response of <ajax-xml>some text</ajax-xml> when you invoke http://localhost:8000/simple. You may get a "restricted API" in eclipse IDE, you could overcome this by removing and adding the rt.jar via the build path or you could try the following from the preferences menu go into Java --> Compiler --> Errors/Warnings --> Depricated and Restricted API and change the "forbidden reference" from "Error" to "Warning".



More JavaScript Q&A

Labels:

2 Comments:

Blogger Akaas Developer said...

here i have collected lots of JavaScript Interview Questions and Answers

kindly have a look this would help you a lot

Regards,

Akaas Developer

questions-interviews.com

3:30 PM, August 06, 2012  
Anonymous Anonymous said...

function test(){
setTimeout(myobj1.myfunction, 1000);
}

A. The output in the alert will be "x is not defined". This is because the "this" will be referring to the default global object -- window. The above code can be fixed by replacing the test() function as shown below.

function test(){
setTimeout(function(){
myobj1.myfunction()},
1000);
}
====================================
Just change and works:
function test(){
setTimeout(myobj1.myfunction(), 1000);
}

There are somethings , is it?

10:14 AM, October 02, 2012  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home