Authored by Peter Rybin , Chrome DevTools team
In this short guide we'll review some new Chrome DevTools features for "function scope" and "internal properties" by exploring some base JavaScript language concepts.
Let's start with closures – one of the most famous things in JS. A closure is a function, that uses variables from outside. See an example:
function A(a, b, c) {
var ar = [a, b, c];
return function B(i) {
return ar[i];
};
}
var b = A('Here', 'I', 'am');
console.log( b(1) );
The first statement calls A
that creates local array, returns function B
(saved in variable b
) and finishes.
The second statement calls function B
(b
) that returns an array item. That means that array ar
from A
has remained existing since A
finished. But where was it stored? Of course, in b
! But how exactly? In some property maybe? No. It's a core language feature, that a function can bear outside variables and there is no other way to access them but calling the function.
From now on, the debugger makes it explicitly visible. Get a function instance b
from the example above and expand its properties. A sub-node called <function scope>
should be there. It's where values of all bound variables will be shown. Those are the variables the function will use when called.
The other thing that DevTools debugger now shows is internal properties.
Suppose your code got a value s
and does the following operation:
s.substring(1, 4) // returns 'ell'
Do you think that s
is a string? Not necessarily. It also can be a string object wrapper. Try the following in watch expressions:
"hello"
Object("hello")
First is a regular string value, the second is a full-featured object. As confusing as it could be, the two values behave almost identically. But the second one has real properties and you can set your own too. Expand the properties list and you will notice, how it's not a completely regular object: it will have an internal property [[PrimitiveValue]] , where the original string value is stored. You cannot access this property from your code, but you can see it in DevTools debugger now.
Who else has internal properties? It's bound functions. This is also a sort of wrapping, but for functions. Try executing these 2 statements:
function Sum(a, b) { return a + b; }
var inc = Sum.bind(null, 1); // binds a=1
If you put Sum
and inc
in watch expression section and compare them, you'll learn, that both are functions. But inc
is a non-transparent one: you cannot see neither its text nor open its declaration, much unlike Sum
.
That's how bound functions work. However, since now all the necessary data is shown in debugger as internal properties: among other properties of 'inc' (not very interesting), you will find [[BoundTarget]], [[BoundArgs]] and [[BoundThis]]. They indicate that inc
is a bound function first of all, and also it tells you all about it: that is wraps Sum
function, binds first argument with value 1
and passes null
as this
.