Sunday May 11, 2008

E4X assignment gotcha

Obscure TIP Warning

E4X allows direct embedding of XML literals inside JavaScript which make it very easy to work with XML inside JavaScript. Recently while working on a Firefox extension I got bit by some unexpected behavior of an XML variable assignment operator (=). Basically it clones the XML document fragment on the right hand side of assignment operator. The following program demonstrates the behavior.

<html>
<head>
<title>E4X</title>
<script>
function e4x() {
var languages = <languages></languages>;
alert("initial value of variable 'languages'=:\\n" + languages.toXMLString());
var javascript = <scripting>JavaScript</scripting>
alert("initial value of variable 'javascript':\\n" + javascript.toXMLString());
languages.scripting = javascript;
alert("after adding 'javascript' variable as a child node - value of variable 'languages':\\n" + languages.toXMLString());
javascript.version = <version>1.2</version>
alert("after adding version node - value of variable 'javascript':\\n" + javascript.toXMLString());
alert("after adding version node to variable 'javascript' - value of variable 'languages':\\n" +
languages.toXMLString() +
"\\nvalue of variable 'languages' does not reflect the changes made to the value of variable 'javascript'.");
}
</script>
</head>
<body onload="e4x();">
</body>
</html>

You can try this program (if you are using Firefox) by clicking here

 

Friday Apr 18, 2008

Nested JavaScript functions and Non-static Inner Classes in Java

 

I am a Java programmer and understand the Java language concepts such as inner classes and scoping rules well. I have been learning JavaScript and trying to understand the scoping rules in JavaScript. Here are some of my observations about the similarities and differences between some aspects of nested JavaScript functions and Non-static inner classes.

 JavaScript
 Java
var global = 0;
function outerFunction() {
var outerLocal = 1;
function innerFunction() {
var innerLocal = 2;
// Can access outerLocal here
// Can access global here
}

return innerFunction;
}

 

 

 


outerFunction.staticVar = 10; 
// elsewhere
function callingFunction() {
// Get a reference to innerFunction()
var refToOuterDotInner = outerFunction();
refToOuterDotInner();

 

public class Outer() {
public static int staticField = 10;
private int outerLocal = 1;
public class Inner() {
private int innerLocal = 2;

private void innerMethod() {

int methodLocal = 4;
// Can access innerLocal here
// Can access outerLocal here
}
}

public Inner getInner() {
return new Inner();
}
}

// elsewhere
public void callingMethod() {
Outer outer = new Outer();
Inner innerInstance = outer.getInner();
// Invoke method of inner class
inner.innerMethod();
}

innerFunction() is analogous to --------->

The scope of innerFunction() maps to two concepts in Java world - the scopes of innerMethod() and the instance of Inner class.

The execution call stack of innerFunction() maps to the innerMethod() though.

 innerMethod() and instance of Inner class

I think this is the source of confusion for Java programmer. At least it was to me.


Three scopes when the innerFunction is executing:

  • Global
  • scope of outerFunction
  • scope of innerFunction - maps to last two scopes on Java side

Three scopes when innerMethod() is executing.

  • No equivalent in Java
  • Outer instance scope
  • Inner instance scope
  • innerMethod() local scope

outerLocal in outerFunction is analogous to --------->

outerLocal is private to outerLocal but can be accessed from innerFunction() .

outerLocal field of an instance of Outer class.

outerLocal is private to the instance of Outer class but can be accessed from innertMethod() .

In terms of scope level innerLocal is analogous to --------->methodLocal and innerLocal
no analogue
the Outer class instance can be accessed using Outer.this

call stack involves:

innerFunction()
callingFunction()

call stack:

innerMethod()
callingMethod()

outerFunciton.staticVar is analogous to --------->

Note the absence of  () after outerFunction.

static access to Outer.staticField

 

The scoping and access level rules of the inner functions allow for closures (a powerful concept) in JavaScript.

Do you have any insights to share?
 

Monday Mar 31, 2008

TIP: Using Object.prototype.toString.apply(...);

You can use Object.prototype.toString.apply(<any JavaScript object>); displays the value returned by primordial toString() function even if the object's constructor function overrides the toString() function.

 For example (Array overrides the toString() function) :

alert([1,2,3].toString());                         => '1,2,3'
alert(Object.prototype.toString.apply([1,2,3]));   => '[object Array]' // better info than the next line
alert(typeof [1,2,3]); => 'object' // does not tell it is an Array

 

TIP: You can evaluate expressions like the above in the Firefox's Tools:Error Console's Evaluate text field.

Saturday Mar 29, 2008

Notes on JavaScript functions and objects

functions

static (or definition) context

  • All functions have a property named prototype.1 The value of prototype is an object2 with a property named constructor.3 The value of constructor is the function itself.4
  • All functions have a property called length which specifies the expected number of parameters as declared in function signature.5
  • The value of constructor property of a function is the function Function6. That is because, the hidden super instance of a function is the value of the prototype property of the function Function.7

execution context

  • While a function executes there is a special variable arguments that holds the actual arguments that were passed in when the function was invoked.
  • While a function executes there is a special variable arguments which is of type Arguments which is an array-like object with a property length which gives the number of actual parameters passed in during invocation.
  • The formal parameter names are really aliases of arguments object's indexed properties indexed by the ordinal number of the formal parameter.
  • While a  function executes there is a special variable arguments.callee holds a reference to the function object itself. Thus  arguments.callee.length gives us the number of expected parameters.
  • For example:
function f(p1, p2) {
// p1 is alias of arguments[0]
// p2 is alias of arguments[1]
// you can access rest of the parameters using arguments[3] thru arguments[n]
// if f was invoked like this f(10, 20, 30, 40):
// the value of p1 and arguments[0] is 10
// the value of p2 and arguments[1] is 20
// the value of arguments[2] is 30
// the value of arguments[3] is 40
// the value of arguments.length is 4 i.e. four parameters were passed in
// the value f.length is 2 - two parameters p1 and p2 declared in function declaration
// the value arguments.callee is the function f itself. This works for anonymous functions also.
// This allows writing recursive functions even in case of anonymous functions.
} 

Function function

static (or definition) context

  • Function being a function has a property named prototype. The value of prototype is an anonymous function function(){} with a property named constructor. The value of constructor is the function Function.
  • The value of constructor property of function Function is function Function. That is because the hidden super instance of a function is the value of the prototype property of function Function.

objects such as {} or new Object()

  • The constructor of an object such as {} or new Object{} of course is function Object.8
  • All objects inherit properties from a hidden super instance - the prototype object. The prototype object is the same as the value of the prototype property of function which was used to create the object using the new operator. Note: objects do not have a property named prototype.
  • The inherited properties behave in a copy-on-set manner.
  • All objects inherit a property named constructor from their hidden super instance - the prototype object.9

Object function

static (or definition) context

  • Object being a function has a property named prototype. The value of prototype is an anonymous object {} with a property named constructor.10 The value of constructor is the function Object.11
  • The value of constructor property of function Object is function Function. That is because the hidden super instance of a function is the value of the prototype property of function Function.
Let us say we have code like this:
function Rectangle(width, height) { 
this.width = width;
this.height = height;
}

var twoByFourRectangle = new Rectabgle(2, 4);

+--------------------------------------+
inherits | +---------constructor property ----+ | +----------------------------------+
from | | | | inherits | |
| v | v from v |
function Function --- prototype property---> function(){} <----- function Object --- prototype property---> {constructor: Object}
\^ \^
inherits | +---------------------------------------+ |
from | | | | inherits
| v | | from(?)
function Rectangle --- prototype property ----> {constructor: Rectangle}--+
\^
inherits |
from |
|
object twoByFourRectangle --- width property ----> 2
+--- height property --> 4

1  alert("prototype" in Rectangle);                   => 'true'
2  alert(Rectangle.prototype);                        => '[object Object]'

3 alert("constructor" in Rectangle.prototype); => 'true'
4  alert(Rectangle.prototype.constructor);            => '[function Rectangle]'
5 alert(Rectangle.length);                           => '2'

6 alert(Rectangle.constructor) => 'function Function() {[native code]}'

7  alert(Rectangle.constructor.prototype)             => 'function(){}'

8 alert({}.constructor); => 'function Object() {[native code]}'

9 alert("constructor" in {}); => 'true'

10 alert(Object.prototype); => '[object Object]'

11 alert(Object.prototype.constructor);               => 'function Object() {[native code]}'
TIP: You can evaluate expressions like the above in the Firefox's Tools:Error Console's Evaluate text field.


Tricky huh? It was for me.

Tuesday Jan 22, 2008

Improved Callstack information in JavaScript

In this post I blogged about a simple function to get the call stack in JavaScript. Here is an improved variant of the same function:

/\*\*
\* This function returns an array of objects that contain the information about call stack.
\*/
function callstack() {
function StackFrame(funcName, funcSource, flName, lnNumber) {
this.functionName = funcName;
this.functionSource = funcSource;
this.fileName = flName;
this.lineNumber = lnNumber;
}
StackFrame.prototype.toString = function() {
return 'at ' + this.functionName + '(' + this.fileName + ':' + this.lineNumber + ')' ;
};
StackFrame.prototype.toHtml = function() {
return '<table border="0">' +
'<tr valign="top"><td><b>Name: </b></td><td>' + this.functionName + '</td></tr>' +
'<tr valign="top"><td><b>File: </b></td><td>' + this.fileName + '</td></tr>' +
'<tr valign="top"><td><b>Line: </b></td><td>' + this.lineNumber + '</td></tr>' +
'<tr valign="top"><td><b>Source:</b></td><td>' +
( this.functionSource ?
'<pre>' + this.functionSource.toString().replace(/\\</g, '&lt;').replace(/\\>/g, '&gt;') + '</pre>' :
'unavailable') + '</td></tr>' +
'</table>'
;

};
var stackFrameStrings = new Error().stack.split('\\n');
// remove first two stack frames
stackFrameStrings.splice(0,2);
var stackFrames = [];
for (var i in stackFrameStrings) {
// a stack frame string split into parts
var stackFrame = stackFrameStrings[i].split('@');
if (stackFrame && stackFrame.length == 2) {
stackFrames.push(
// Stackframe object
new StackFrame(stackFrame[0],
eval(stackFrame[0].replace(callstack.sansParenthesisRE,'')),
stackFrame[1].match(callstack.fileNameLineNumberRE)[1], // first group
stackFrame[1].match(callstack.fileNameLineNumberRE)[2] // second group
)
);
}
}
return stackFrames;
}
callstack.sansParenthesisRE = /[(][\^)]\*[)]/;
callstack.fileNameLineNumberRE = /(.\*):(\\d+)$/;

Here is how it canbe used. The callstack function code above is assumed to be stored in a file named Utilities.js .

<html>
<head>
<title>Callstack</title>
<script src='Utilities.js'></script>
<script>
function called() {
var cs = callstack();
document.write(cs[0].toHtml());
document.write(cs[1].toHtml());
document.write(cs[2].toHtml());
}
function caller() {
called();
}
</script>
</head>
<body onload="caller();">
</body>
</html>

Here is the output as displayed in the browser (FireFox):

Name: called()
File: file:///languages/javascript/Callstack.html
Line: 7
Source:
function called() {
var cs = callstack();
document.write(cs[0].toHtml());
document.write(cs[1].toHtml());
document.write(cs[2].toHtml());
}
Name: caller()
File: file:///languages/javascript/Callstack.html
Line: 13
Source:
function caller() {
called();
}
Name: onload([object Event])
File: file:///languages/javascript/Callstack.html
Line: 1
Source:
function onload(event) {
caller();
}


 

Monday Dec 24, 2007

Callstack information in JavaScript


I have started hacking JavaScript. It has been an interesting learning experience and quite different from Java coding. However some things remain same...here is a function to get the information about current call stack:

/\*\*
 \* This function returns an array of objects that contains information about the current call stack.
 \*/
function callstack() {
    var stackFrameStrings = new Error().stack.split('\\n');
    stackFrameStrings.splice(0,2);
    var stackFrames = [];
    for (var i in stackFrameStrings) {
        var stackFrame = stackFrameStrings[i].split('@');
        if (stackFrame && stackFrame.length == 2) {      
            stackFrames.push(
            {
            functionName: stackFrame[0],
            functionSource: eval(stackFrame[0].replace(/[(][\^)]\*[)]/,'')),
            fileName: stackFrame[1].match(/(.\*):(\\d+)$/)[1],
            lineNumber: stackFrame[1].match(/(.\*):(\\d\*)$/)[2]
            }
            );
        }
    }
    return stackFrames;
}

NOTE: Tested in Firefox.

It uses a mechanism very similar to Java's new Throwable().getStackTrace() to get information about the current call stack. It uses the JavaScript Error object which happens to have a property called stack.  Example usage:

function called() {
    var cs = callstack();
    alert('Self: ' + cs[0].functionName);
    alert('Caller: ' + cs[1].functionName);
}
function caller() {
    called();
}
caller();

This displays two alert dialogs:

Self: called()
Caller: caller()
Please let me know if there is a better way to get similar information. 
About

sandipchitale

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today