object vs closure

Consider this JavaScript function:

1
2
3
4
5
function fn()
{
    var a = 10;
    var b = { name: 'foo', n: 10 };
}

This might produce the following:

I say “might” because specific behaviors depend heavily on implementation. This post takes a V8-centric approach with many diagram shapes linking to relevant source code. In V8, only small integers are stored as values. Also, from now on I’ll show strings directly in objects to reduce visual noise, but keep in mind they exist separately in the heap, as shown above.

Now let’s take a look at closures, which are simple but get weirdly hyped up and mythologized. Take a trivial JS function:

1
2
3
4
5
function add(a, b)
{
        var c = a + b;
        return c;
}

This function defines a lexical scope, a happy little kingdom where the names a, b, and chave precise meanings. They are the two parameters and one local variable declared by the function. The program might use those same names elsewhere, but within add that’s what they refer to. And while lexical scope is a fancy term, it aligns well with our intuitive understanding: after all, we can quite literally see the bloody thing, much as a lexer does, as a textual block in the program’s source.

Having seen stack frames in action, it’s easy to imagine an implementation for this name specificity. Within add, these names refer to stack locations private to each running instance of the function. That’s in fact how it often plays out in a VM.

So let’s nest two lexical scopes:

1
2
3
4
5
6
7
8
9
function makeGreeter()
{
    return function hi(name) {
        console.log('hi, ' + name);
    }
}

var hi = makeGreeter();
hi('dear reader'); // prints "hi, dear reader"

That’s more interesting. Function hi is built at runtime within makeGreeter. It has its own lexical scope, where name is an argument on the stack, but visually it sure looks like it can access its parent’s lexical scope as well, which it can. Let’s take advantage of that:

1
2
3
4
5
6
7
8
9
function makeGreeter(greeting)
{
    return function greet(name) {
        console.log(greeting + ', ' + name);
    }
}

var heya = makeGreeter('HEYA');
heya('dear reader'); // prints "HEYA, dear reader"

A little strange, but pretty cool. There’s something about it though that violates our intuition:greeting sure looks like a stack variable, the kind that should be dead after makeGreeter()returns. And yet, since greet() keeps working, something funny is going on. Enter the closure:

The VM allocated an object to store the parent variable used by the inner greet(). It’s as ifmakeGreeter’s lexical scope had been closed over at that moment, crystallized into a heap object for as long as needed (in this case, the lifetime of the returned function). Hence the nameclosure, which makes a lot of sense when you see it that way. If more parent variables had been used (or captured), the Context object would have more properties, one per captured variable. Naturally, the code emitted for greet() knows to read greeting from the Context object, rather than expect it on the stack.

Here’s a fuller example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function makeGreeter(greetings)
{
    var count = 0;
    var greeter = {};

    for (var i = 0; i < greetings.length; i++) {
        var greeting = greetings[i];

        greeter[greeting] = function(name) {
            count++;
            console.log(greeting + ', ' + name);
        }
    }

    greeter.count = function() { return count; }

    return greeter;
}

var greeter = makeGreeter(["hi", "hello", "howdy"])
greeter.hi('poppet'); // prints "howdy, poppet"
greeter.hello('darling'); // prints "howdy, darling"
greeter.count(); // returns 2

Well… count() works, but our greeter is stuck in howdy. Can you tell why? What we’re doing with count is a clue: even though the lexical scope is closed over into a heap object, the valuestaken by the variables (or object properties) can still be changed. Here’s what we have:

There is one common context shared by all functions. That’s why count works. But the greeting is also being shared, and it was set to the last value iterated over, “howdy” in this case. That’s a pretty common error, and the easiest way to avoid it is to introduce a function call to take the closed-over variable as an argument. In CoffeeScript, the do command provides an easy way to do so. Here’s a simple solution for our greeter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function makeGreeter(greetings)
{
    var count = 0;
    var greeter = {};

    greetings.forEach(function(greeting) {
        greeter[greeting] = function(name) {
            count++;
            console.log(greeting + ', ' + name);
        }
    });

    greeter.count = function() { return count; }

    return greeter;
}

var greeter = makeGreeter(["hi", "hello", "howdy"])
greeter.hi('poppet'); // prints "hi, poppet"
greeter.hello('darling'); // prints "hello, darling"
greeter.count(); // returns 2

It now works, and the result becomes:

That’s a lot of arrows! But here’s the interesting feature: in our code, we closed over two nested lexical contexts, and sure enough we get two linked Context objects in the heap. You could nest and close over many lexical contexts, Russian-doll style, and you end up with essentially a linked list of all these Context objects.

Of course, just as you can implement TCP over carrier pigeons, there are many ways to implement these language features. For example, the ES6 spec defines lexical environments as consisting of an environment record (roughly, the local identifiers within a block) plus a link to an outer environment record, allowing the nesting we have seen. The logical rules are nailed by the spec (one hopes), but it’s up to the implementation to translate them into bits and bytes.

You can also inspect the assembly code produced by V8 for specific cases. Vyacheslav Egorovhas great posts and explains this process along with V8 closure internals in detail. I’ve only started studying V8, so pointers and corrections are welcome. If you know C#, inspecting the IL code emitted for closures is enlightening – you will see the analog of V8 Contexts explicitly defined and instantiated.

Closures are powerful beasts. They provide a succinct way to hide information from a caller while sharing it among a set of functions. I love that they truly hide your data: unlike object fields, callers cannot access or even see closed-over variables. Keeps the interface cleaner and safer.

FROM HERE

another good one

that=this in javascript

Watch Out: Callbacks And Closures Sometimes Do Not Play Nicely

Of course there are always gotchas with JavaScript. Lets define a callback function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var createCallBack = function() { //First function
    return new function() { //Second function
        this.message = "Hello World";

        return function() { //Third function
            alert(this.message);
        }
    }
}

window.onload = createCallBack(); //Invoke the function assigned to createCallBack

Lets examine the above code. There are three function operators:

  1. The first function operator creates a function object and is assigned tocreatCallBack.
  2. The second function operator uses the constructor invocation pattern to create a new object.
  3. The third function operator is the result of the return statement. It is a function object and because it is an instance of Object, it gets returned instead of a new object (even though though the function was invoked with new – read constructor invocation pattern for more info).

When invoking the createCallBack variable, what gets passed to the window.onloadevent handler is the result of what is returned by the seond function operator, which is the code in the third function operator. Did you get that? Read this paragraph again until you understand, and if not, stick this code into your browser and play with it.

The above code looks alright, except that undefined gets alerted to the screen (try it for yourself). It turns out that when an event handler invokes a callback function, the function invocation pattern is used. This results in the this parameter being bound to the global object (it is one of the pitfalls of the function invocation pattern) instead of to the object that was created with the constructor invocation pattern. To note that this problem only occurs when one uses the constructor invocation pattern with callbacks like I have illustrated above. To get around this, apply the standard fix for function invocation by declaring a that variable to point to this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var createCallBack = function() { //First function
    return new function() { //Second function
        var that = this;
        this.message = "Hello World";

        return function() { //Third function
            alert(that.message);
        }
    }
}

window.onload = createCallBack(); //Invoke the function assigned to createCallBack

Since the function invoked by the event handler (the third function) is a closure, it has access to the that variable (which is private), and so it has access to the new object created by the constructor invocation pattern.

Read More

 

JavaScript 中的函数既可以被当作普通函数执行,也可以作为对象的方法执行,这是导致 this 含义如此丰富的主要原因。一个函数被执行时,会创建一个执行环境(ExecutionContext),函数的所有的行为均发生在此执行环境中,构建该执行环境时,JavaScript 首先会创建 arguments变量,其中包含调用函数时传入的参数。接下来创建作用域链。然后初始化变量,首先初始化函数的形参表,值为 arguments变量中对应的值,如果 arguments变量中没有对应值,则该形参初始化为 undefined。如果该函数中含有内部函数,则初始化这些内部函数。如果没有,继续初始化该函数内定义的局部变量,需要注意的是此时这些变量初始化为 undefined,其赋值操作在执行环境(ExecutionContext)创建成功后,函数执行时才会执行,这点对于我们理解 JavaScript 中的变量作用域非常重要,鉴于篇幅,我们先不在这里讨论这个话题。最后为 this变量赋值,如前所述,会根据函数调用方式的不同,赋给 this全局对象,当前对象等。至此函数的执行环境(ExecutionContext)创建成功,函数开始逐行执行,所需变量均从之前构建好的执行环境(ExecutionContext)中读取。

reduce function for array in javascript

Parameters

callback
Function to execute on each value in the array, taking four arguments:

previousValue
The value previously returned in the last invocation of the callback, or initialValue, if supplied. (See below.)
currentValue
The current element being processed in the array.
index
The index of the current element being processed in the array.
array
The array reduce was called upon.
initialValue
Optional. Object to use as the first argument to the first call of the callback.
[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, index, array) {
  return previousValue + currentValue;
}, 10);

Examples

 Example: Flatten an array of arrays

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
  return a.concat(b);
});
// flattened is [0, 1, 2, 3, 4, 5]

 

Consider the case of a library system which needs to show potential donors its effectiveness at spreading knowledge. In order to do that, it must determine how many book-checkouts there were last year. (Not total of all checkouts, since a single checkout may be for more than one book.)

Their data is stored in an object like this:

var books = [
    {
        title: "Showings",
        author: "Julian of Norwich",
        checkouts: 45
    },
    {
        title: "The Triads",
        author: "Gregory Palamas",
        checkouts: 32
    },
    {
        title: "The Praktikos",
        author: "Evagrius Ponticus",
        checkouts: 29
    }
];

The traditional C-style way to get at that number would be something like this:

var bookCheckouts = 0;

for (var i = 0; i < books.length; i++) {
    bookCheckouts = bookCheckouts + books[i].checkouts;
}

But using reduce, we can think more directly about the problem itself:

// Get an array of checkout values only
var bookCheckouts = books.map(function(item) {
    return item.checkouts;
});

// Sum the array's values from left to right
var total = bookCheckouts.reduce(function(prev, curr) {
    return prev + curr;
});

While it may look a little foreign at first, this example is more explicit about the problem than thefor version is. Namely, dealing only with the checkouts property, and totaling them. And if you are familiar with the idioms, you can make it almost as concise.

// Get total of book checkouts
var total = books
            .map(function(b) { return b.checkouts; })
            .reduce(function(p, c) { return p + c; });

So how does that reduce method work? It takes an array of values and executes the function (almost!) once for each item in the array. The value of prev is the result of the calculations up to this point. Let’s take a look:

[1, 2, 3].reduce(function(prev, curr, index) {
    console.log(prev, curr, index);
    return prev + curr;
});

// Outputs:
// 1, 2, 1
// 3, 3, 2
// 6

As you can see, the callback actually didn’t iterate over the first element of the array. Instead,prev was set to the value of the first element. It has to work that way because otherwisereduce wouldn’t have a starting value for prev.

The function ran three times, but on the last call, it wasn’t given a current element since there were no elements left in the array. That behavior is a little confusing to read through, but is quite easy to use.

Here is another example:

[1, 2, 3].reduce(function(prev, curr, index) {
    console.log(prev, curr, index);
    return prev + curr;
}, 100);

// Outputs:
// 100 1 0
// 101 2 1
// 103 3 2
// 106

In addition to the callback function, we also passed in an initial value for prev. You’ll note that in this case, the callback did iterate over the first element in the array, since it had an initial value to work with.

It should be noted that your callback function also has access to the array itself as a parameter.

[1, 2, 3].reduce(function(prev, curr, index, arr) {
    // Do something here
});

Is reduce only good for working with numbers? By no means. Consider this:

var relArray = [
    ["Viola", "Orsino"],
    ["Orsino", "Olivia"],
    ["Olivia", "Cesario"]
];

var relMap = relArray.reduce(function(memo, curr) {
    memo[curr[0]] = curr[1];
    return memo;
}, {});

// Outputs: {
//    "Viola": "Orsino",
//    "Orsino": "Olivia",
//    "Olivia": "Cesario"
// }
console.log(relMap);

This time we used reduce to transform the relationship data from an array of arrays into an object where each key value pair describes the relationship. You’ll also see that instead of naming the parameter prev as I did before, I used the term memo. That’s because in this case, memo is a more descriptive name for the actual value being passed in (an object collecting new properties.)

The reduce method is good for any sort of situation where we want to take an array and boil it down into a new value in steps that have access to one or two of the array elements at a time.

Want to use reduce in IE8 or IE7? Take a look at the Underscore and Lo-Dash libraries.

 

FROM HERE

delete in js

The delete operator removes a property from an object.

delete is only effective on an object’s properties. It has no effect on variable or function names.

If the object inherits a property from a prototype, and doesn’t have the property itself, the property can’t be deleted by referencing the object. You can, however, delete it directly on the prototype.

function Foo(){}
Foo.prototype.bar = 42;
var foo = new Foo();

// returns true, but with no effect, 
// since bar is an inherited property
delete foo.bar;           

// logs 42, property still inherited
console.log(foo.bar);

// deletes property on prototype
delete Foo.prototype.bar; 

// logs "undefined", property no longer inherited
console.log(foo.bar);

javascript IE memory leak

An unfortunate side effect of closures is that they make it trivially easy to leak memory in Internet Explorer. JavaScript is a garbage collected language — objects are allocated memory upon their creation and that memory is reclaimed by the browser when no references to an object remain. Objects provided by the host environment are handled by that environment.

Browser hosts need to manage a large number of objects representing the HTML page being presented — the objects of the DOM. It is up to the browser to manage the allocation and recovery of these.

Internet Explorer uses its own garbage collection scheme for this, separate from the mechanism used for JavaScript. It is the interaction between the two that can cause memory leaks.

A memory leak in IE occurs any time a circular reference is formed between a JavaScript object and a native object. Consider the following:

function leakMemory() {
    var el = document.getElementById('el');
    var o = { 'el': el };
    el.o = o;
}

The circular reference formed above creates a memory leak; IE will not free the memory used by el ando until the browser is completely restarted.

The above case is likely to go unnoticed; memory leaks only become a real concern in long running applications or applications that leak large amounts of memory due to large data structures or leak patterns within loops.

Leaks are rarely this obvious — often the leaked data structure can have many layers of references, obscuring the circular reference.

Closures make it easy to create a memory leak without meaning to. Consider this:

function addHandler() {
    var el = document.getElementById('el');
    el.onclick = function() {
        el.style.backgroundColor = 'red';
    };
}

The above code sets up the element to turn red when it is clicked. It also creates a memory leak. Why? Because the reference to el is inadvertently caught in the closure created for the anonymous inner function. This creates a circular reference between a JavaScript object (the function) and a native object (el).

There are a number of workarounds for this problem. The simplest is not to use the el variable:

function addHandler(){
    document.getElementById('el').onclick = function(){
        this.style.backgroundColor = 'red';
    };
}

Surprisingly, one trick for breaking circular references introduced by a closure is to add another closure:

function addHandler() {
    var clickHandler = function() {
        this.style.backgroundColor = 'red';
    };
    (function() {
        var el = document.getElementById('el');
        el.onclick = clickHandler;
    })();
}

The inner function is executed straight away, and hides its contents from the closure created withclickHandler.

Another good trick for avoiding closures is breaking circular references during the window.onunloadevent. Many event libraries will do this for you. Note that doing so disables the back-forward cache in Firefox, so you should not register an unload listener in Firefox, unless you have other reasons to do so.

javascript array in depth

What is an Array in JavaScript?

A numerically indexed map of values.

Traditionally an array reserves a continuous allocation of memory of predefined length. In JavaScript this is not the case. A JavaScript array is simply a glorified object with a unique constructor and literal syntax and an additional set of properties and methods inherited from Array.prototype. If this means we make a small sacrifice in performance, it is more than compensated for by its ease of use and the power of its utilities. Unlike its counterparts in certain other languages, JavaScript arrays are a joy to use – this is something they definitely got right.

How do I create a JavaScript Array?

Lets start with the best way. In JavaScript, whenever there is a literal syntax for object creation it generally makes sense to use it.

1
2
3
4
5
6
7
8
9
10
11
//create a new, empty array
var a = [];
//add members to an existing array
a[0] = "Bob";
a[1] = "Mary";
a[2] = "Joe";
//or simply use push
a.push("Jane");
a.push("Carlos");
//create a new array and predefine some members
var b = ["Bob", "Mary", "Joe", "Jane", "Carlos"];

Alternatively you could use the new Constructor syntax. Apart from the obvious drawback of 5-9 additional assaults on your dainty finger pads (the “new” part is effectively optional) there is a more serious issue around ambiguity of intention:

1
2
3
4
5
6
7
8
//create a new array with 8 undefined members
var a = new Array(8);
//create a new array containing two predefined elements
var b = new Array(8,9);
a.length; //8
b.length; //2
a[0]; //undefined
b[0]; //8

These two declarations look strikingly similar yet produce entirely different results. Moreover, lets say someone edits the second statement because they now only want to predefine one element, the number 8, in array b. It’s quite likely they might modify it to the following (and who could blame them?):

1
2
//create a new array containing one predefined element
var b = new Array(8); //Wrong!

Of course this doesn’t do what they wanted. The only way to predefine an array with one primitive number is to use the literal syntax. (Thanks Peter and Dmitry for clarification)

Is there any advantage to using the new Array syntax?

Well it means you can define the length of your array at creation time. But since JavaScript arrays do not require an up front allocation of memory, and they can be lengthened at will any time, that’s a questionable requirement. (Several people pointed out webkit et al have built in optimization when Array length predefined – though there is nothing in the spec to suggest this)

What types of data can an Array contain?

An array can contain any object or primitive type. Multiple data types can co-exist in the same array.

How do I access an Array element?

Array elements are simply object properties and are accessed in the same way as other object properties. Since property identifiers are always strings, the array index is also a string, not a number. However when you use subscript notation (square brackets) to access the property, a number literal can also be used since it will be coerced to a string by the interpreter. Dot notation accessors will not work for array member access because literal property identifiers can’t start with a number (again, all these behaviours derive from generic object property rules, they are not array-specific)

1
2
3
var a = ["banana", Math.min, 4, "apple"];
a['1']; //min()
a[2]; //4

How should I iterate over the elements of an array?

Typically it makes sense to use the standard for loop:

1
2
3
4
var a = ["banana", Math.min, 4, "apple"];
for (var i=0; i < a.length; i++) {
    console.log(a[i]);
}

If your array is a long one you may be worried about the additional cost of requesting array.length on every iteration. To workaround this you can define the array length up front:

1
2
3
4
5
var a = makeBigArray();
for (var i=0,  aLength = a.length; i < aLength; i++) {
    console.log(a[i]);
}

Using a for…in statement for array iteration is not advised because you may also pick up enumerable properties from the prototype (see below)

Which properties are unique to Arrays?

The most important array property is length (strings and functions have length too but the array definition of length is unique)

Array.length is NOT a read-only value, you can set it as you wish.

ECMA specifies:
The length property of this Array object is always numerically greater than the name of every property whose name is an array index

In other words its (the numeric value of the last index) + 1

Array’s are not upper-bound. You can add an element at an index greater than (length – 1) and the length property will be modified based on the above definition. Array’s have a maximum length but its too big for you to worry about.

1
2
3
4
5
6
var a = [3,4,1];
a.length; //3
a[20] = 2;
a.length; //21
//element indexes 3-19 automatically created with value initialized to undefined
a[18]; //undefined

Arrays are lower-bound to zero. If you try to add a value at a negative index you will just be writing a regular object property (see also “associative arrays” below)

1
2
3
4
5
var a = [];
a[-1] = "giraffe";
a[-1]; //"giraffe"; //because still using a regular object property accessor
a.length; //0
a.toString(); //""

You can manipulate the contents of an existing array by updating its length value. If you reduce the length property of an existing array, members with indexes greater than or equal to the new length get discarded (this turns out to be the only way to remove indexes from an array – you can delete an element but this will only delete the value and leave the index in place – i.e. your array becomes “sparse” = it gets holes in it)

1
2
3
4
5
var a = [0,1,2,3,4,5,6];
a.length; //7
a.length = 5;
a.toString(); //"0,1,2,3,4"
a[6]; //undefined

Conversely if you increase the length of an existing array by n your array appears to get n new members, each with its value initialized to undefined – however as Dmitry Soshnikov points out, this is the standard response to accessing a non existent property. In reality nothing has changed except the array length.

1
2
3
4
5
6
7
8
var a = [0,1,2,3,4,5,6];
a.length; //7
a[9]; //undefined
a[59]; //undefined
a.length = 10;
a.toString(); //"0,1,2,3,4,5,6,,,"
a[9]; //undefined
a[59]; //undefined

There are two additional pseudo-properties of arrays: index and input. These properties are only present in arrays created by regular expression matches

 

add InterpretedFunction to the java scriptEngine using eval

RhinoScriptEngine

This is the typical engine we use for js evaluation.

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/com/sun/script/javascript/RhinoScriptEngine.java

without ScriptContext

import javax.script.*;

public class CallFunction {

    /**
     * @param args
     * @throws Exception oops!
     */
    public static void main(String[] args) throws Exception {
        ScriptEngine js = new ScriptEngineManager().getEngineByExtension("js");
        js.getContext().setAttribute("out", System.out, ScriptContext.ENGINE_SCOPE);
        Object a = js.eval(
                "out.println('Defining function a...');" +
                "function a() {out.println('hello from JavaScript!'); }" +
                "function foobar() {out.println('in foobar() definition');}" +    
                "out.println('Done!.');"
        );

        System.out.println(js.get("a")); // InterpretedFunction
        SimpleBindings bindings = new SimpleBindings();
        bindings.put("foobar",js.get("a"));
        js.eval("foobar();", bindings); // hello from JavaScript
        js.eval("foobar();"); // in foobar() definition
    }
}

When you get back the reference to a function, you need to ask the engine to execute that function for you. And although not pretty, asking js to eval() it for you with a specific set of bindings will actually do the job for you. You need to take care that the variables you’re manipulating belong to the right scope; I guess it’s easy to make mistakes here.

using ScriptContext

To make it less error-prone, we could call the eval with the ScriptContext. something like this:

import javax.script.*;

public class CallFunction {

    /**
     * @param args
     * @throws Exception oops!
     */
    public static void main(String[] args) throws Exception {
        // or:  js = new ScriptEngineManager().getEngineByName("JavaScript");
        ScriptEngine js = new ScriptEngineManager().getEngineByExtension("js");
        ScriptContext scriptContext = new SimpleScriptContext();
        Bindings scriptScope = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
        scriptScope.put("out", System.out);


        // this will add the function names into the scriptScope as key, value is the function itself.
        // later by calling scriptEngine.eval("fucntionName()", scriptContext) to invoke the function.
        js.eval(
            "out.println('Defining function a...');" +
                "function a() {out.println('hello from JavaScript!'); }" +
                "function foobar() {out.println('in foobar() definition');}" +
                "out.println('Done!.');"
            , scriptContext);

       js.eval("a()", scriptScope); // hello from JavaScript!
       js.eval("foobar()", scriptScope); // in foobar() definition
    }
}