Friday, August 10, 2012

This blog has moved

THIS BLOG HAS MOVED
Thanks for coming to check out my latest finding on JS.Next. Unfortunately we have stopped using this site and have moved away from Blogger. Our new blog is at: http://JSdotNext.com . This is an Octopress blog hosted on Heroku.

Please update your bookmarks and remember to head over to the new blog to get the latest findings.

Wednesday, July 18, 2012

LET, the new VAR

If you are first getting into the changes that will be coming down once the ES6 spec is finalized, then let might be the perfect place for you to start. It is simple enough to beginners and monumental enough for experts. Using let will, in a very real sense, change the way that we write JavaScript.

Basically it's...
At it's very basic level, let is a replacement for var. Instead of: 

    var foo = 'bar';

We'll say:

    let foo = 'bar';

Considering most of the comments I found about let from the JS community, it appears that most people will attempt to use let as exclusively as possible.

Seems anti-climactic
If all let did was to simply replace our current var syntax, then it wouldn't have a point. However, there are some very beautiful things that we get when using let instead of var.


In order to appreciate pretty much the rest of this post, you will need to have a firm understanding of Variable Hoisting. In the book we covered it extensively. For the sake of brevity, and given that this is a blog and not a book, I would like to refer anyone with questions about Variable Hoisting to this video, where it is explained very well.  


I can haz scope control?
Any developer who has experience with C-based languages understands scope control. Consider the following Java snippet:

    if(true){
        int myInt = 0;
    }


Knowing what we know about these C-based languages, the int inside the if-statement is not available outside of the if-statement. If the next line of code tried to reference myInt, your code wouldn't compile because myInt was locked inside the if-statement.

Now let's try to same thing with var:

    if(true){
        var mynum = 0;
    }


We have an issue here. The code would lead you (the developer) to believe that mynum is isolated inside the if-statement. But we all know that isn't true though, don't we. The JavaScript Compiler re-structured the code to look as follows:

    var mynum = undefined;
    if(true){
        mynum = 0;
    }


Since mynum's declaration was hoisted to the top of the current scope, the mynum variable will be available through out the entire scope.

Disclaimer
I am not saying that the way var behaves is a bad thing. It can be very useful. Having said that, one of the downsides of how var behaves is that the code will read differently than it will run. This makes it tough to spot errors some times.

let in action
Let's do the same thing again, but instead of using var we will use let.

    if(true){
        let mynum = 0;
    }


In this situation, our JavaScript will run just like it reads. The variable mynum is scoped inside of that if-statement. Let solves some of our scoping issues.

While the above examples are extremely trivial, there is a lot to consider and re-learn when we start to use let.

let it be
As I mentioned before, the book covered these areas much more slowly and in greater detail, hopefully answering any questions that I left today. Here is a list of let tips:

  • Not sure if IE10 will even support this. If you have to support IE, then let it be. 
  • If you try to declare two let variables inside the same scope with the same variable name, you will get an error. 
  • let also applies to function expressions. 
  • When you read about ES6 Destructuring and Looping, let will appear again. 
  • There was talk about forcing an opt-in environment where var would be disallowed and only let would be allowed. I am not sure what came of that. 
  • let will allow for better IDE support with JavaScript. 
  • let should reduce memory usage at runtime, possibly speeding things up. 
As always, if I have made any mistakes, please point them out here so that we may all learn. 

Tuesday, July 17, 2012

Function.prototype.toString()

Not a lot new in the fn.toString() area. After reading through the latest Spec and the es-discuss thread on the topic, I understood a few things about Function.prototype.toString that I can impart.

Before I mention any changes, I should inform everyone that Function.prototype.toString already existed in the ES spec. It isn't new to ES6. If you haven't ever used it, go ahead and try it out now. Open your console or your scratchpad and try it. If you like. However, there may be a few things that I can tell you about this functionality.

An interesting fact here: none of the browsers implemented Function.prototype.toString the way that the ES3 and ES5 spec said to. They all did it a different way. So, rather than have everyone change their implementation, they altered the spec to match the current functionality (plus a few changelets). Now we can rest assured that the spec and the functionality match. 

Function Declaration vs Function Expression
Below you will see two functions. They are almost identical. The main difference is that the first one is a Function Declaration, and the second one is a Function Expression. 

    function test1(){
        console.log("This is test1 function");
    }

    var test2 = function(){
        console.log("This is test2 function");
    }



It is fairly obvious what will happen when these methods are called. However calling toString on them will be very different. Look at what we end up with when we call toString on our functions:

    console.log(test1.toString());
        "function test1(){
            console.log('This is test1 function');
        }"

    console.log(test1.toString());
        "function (){
            console.log('This is test2 function');
        }"
Please notice that test1 resulted in a complete implementation, while test2 merely resulted in an anonymous function string. At this point, if we were to eval()uate them, we would have completely different results.

eval(test1)
Calling eval(test1.toString()) at this point would bind a the test1 function to the current scope.

eval(test2)
Calling eval(test2.toString()) at this point will cause a syntax error. In order to get this to work, you would have to do the following: eval("var newfunction = "+test2.toString()). If you append a variable declaration (or rather the string representation of a variable declaration) and THEN eval()uate, everything works fine. Your eval will bind the function to the current scope without any errors.

etc
Other pieces worth mentioning:

  • This will be covered with much more detail in the book. 
  • native functions will return an unusable string, something like: "[native code]"
  • Calling the Function.prototype.toString on a non-function throws an error, ie: Function.prototype.toString.call(123) will throw an error since the number 123 is not a function. 
  • The previous versions of the spec said that Function.prototype.toString should return a Function Declaration compliant string. However, the major browser vendors implemented the aforementioned functionality, making Function Declarations return FD implemented strings, and Function Expressions return anonymous function implemented strings.  
Please message me if there are questions. Also, if I made any mistakes, please add comments to correct me. Thanks!

Monday, July 16, 2012

Arrow Functions

First post: Arrow Functions
Since this is the first post on the new blog, I had to find something interesting to blog about. As I went through the current ES.Next strawman docs and the current ES6 Spec doc, I decided that Arrow Functions would be a good place to start. As I look at all of the features proposed in the Spec, I think that Arrow Functions will be one of the first pieces that people begin to implement.

DISCLAIMER
Please keep in mind that based on the specification, this code will work as I have described it, with minimal-to-no variance among the browser vendors. I would feel a lot more confident if I could test the code before publishing this post. Since I can't test it first, I can either 1) not post this or 2) post it with my best assumptions based on the docs. I am choosing the later.

Reading Material
Anyone looking for some good reading material on the subject, see here:
Example
Unfortunately none of the browser vendors have implemented this piece of ES6 yet, despite it being officially drafted into ES6. Additionally, none of the up-to-date transpilers and poly-fills support it either. Thus, I cannot give you any proven code, as I have no environments, transpilers or poly-fills that support the syntax. So, the provided code will be based on the definition the current official ES6 spec. 

Here is a the basic syntax:

let sq = x => x * x ;

Here we have an Arrow Function Expression. This is an expression that declares a new Arrow Function. In this case, we end up with a function named 'sq'. 'sq' takes one parameter, which is multiplied by itself and then returned.

Parameters (to the left of the arrow =>)
Our 'sq' function takes one parameter, defined by 'x'. Notice 'x' was not wrapped with parens. If your arrow function takes more than one param, the parens will be required. It would look similar to 'let mult = (x, y) => x * y;'

Method Body (to the right of the arrow =>)
Our 'sq' method body has only one line of code. Like 'if' or 'for' statements, we don't need to wrap our method body in braces {} when it only consists of one line. If our method body has more than one line of code, you will need to wrap it with braces. Additionally, notice that I omitted the word 'return' from the code. With one line method bodies, the resulting value is implicitly returned. No 'return' required for one line method bodies. When your method body is more then one line, you will need to explicitly provide a return statement.

Another Example
Let's see another Arrow Function Expression:

var a = {
    name: 'THING-A',
    whoami : function(){
        console.log("I AM THIS",this.name);
    }
};
var b = {
    name: 'THING-B',
    whoami : () => {console.log("I AM THIS",this.name)}
};
a.whoami(); //I AM THIS THING-A
b.whoami(); //I AM THIS THING-B
a.whoami.call(b); //I AM THIS THING-B
b.whoami.call(a); //I AM THIS THING-B ???


Here we have two objects, 'a' and 'b'. 'a' has a 'whoami' function that is a traditional function expression. 'b' has a 'whoami' function that is an arrow function expression. While they appear to be the same, they will behave differently with regard to 'this'. 'a' allows me to reassign 'this' by using 'a.whoami.call' and passing a new scope (b) as the first parameter. However, 'b.whoami.call' doesn't allow for scope reassignment because it is an arrow function. So when you call 'b.whoami.call' and pass a new scope, the new scope is ignored. Arrow Functions are lexically bound to the 'this' of where it is declared. In other words, when an Arrow Function is declared, whatever the scope is at that time, that is 'this'.

The way that Arrow Function relate to their 'this' has a lot of implications. Too many to talk about here. I will cover all of this in the book (once O'Reilly gets the link up for pre-order and e-copies, I will get the link here).

Why add Arrow Functions?
Why add this? We already understood what was going on... so why change it? I think that Brendan Eich has provided a great list of reasons ('Rationale' section):

  • Hard to beat C# and CoffeeScript here (we want the unparenthesized single-parameter form as in C#).
    • TC39 should embrace, clean-up, and extend rather than re-invent or compete with de-facto and nearby de-jure standards.
    • However, we don’t want CoffeeScript’s ->, it’s confusing to have two arrows and dynamic this binding is an oft-fired footgun.
    • Currently we don’t make () or {} in () => {} optional, but we could at risk of losing consensus (but no grammatical bugs bite optionality here).
  • Lexical this matches the dominant cohort measured by Kevin Smith (see the BTF Measurements thread) that either does not use this or wants it lexically bound.
    • Best results after modifying subject code to use method definition shorthand and only then scanning for function.
    • From lexical this it follows that arrow functions are not constructors (no .prototype or [[Construct]]).
  • => parses as if it were a low-precedence (assignment) operator joining a restricted comma expression (implicitly quoted) to a body.
    • This avoids precedence inversion when the body is an AssignmentExpression.
    • No preference for object literal over block (see block vs object literal to keep grammar simple and match expression-statement.
  • TCP compliance “above” expressions – for statements and programs – looks like a mismatch with JS functions, old-style or arrow.
    • return is problematic because users want to write early returns in async callbacks, which under TCP would throw.
    • break and continue in sync callbacks could work well but would reify as exceptions and be observable via finally even if uncatchable.
    • In general the statements vs. expressions rift in JS, inherited via Java from C, means full TCP creates inevitable confusion and bugs.


Eventually they want to add the ability to soft-bind to 'this' so that we have a dynamic-this opt-in option.

As is, I can't wait to get my hands on Arrow Functions! I can't wait to never have to write the following again!
var me = this;