Category: Javascript


Javascript CAPTCHA decoder

ocr_20090125.jpgShaun Friedle created an impressive piece of Javascript which can automatically defeat CAPTCHAs used by the Megaupload file hosting service. While their CAPTCHAs are particularly weak, it’s an impressive Javascript feat that breaks into some new territory, namely Javascript-based optical character recognition. John Resig posted a breakdown of how the software works. Here’s the quick summary:

  1. The HTML 5 Canvas getImageData API is used to get at the pixel data from the Captcha image. Canvas gives you the ability to embed an image into a canvas (from which you can later extract the pixel data back out again).
  2. The script includes an implementation of a neural network, written in pure JavaScript.
  3. The pixel data, extracted from the image using Canvas, is fed into the neural network in an attempt to divine the exact characters being used – in a sort of crude form of Optical Character Recognition (OCR).

Shaun designed the software as a Greasemonkey script that will break CAPTCHAs for Megaupload and automatically trigger a download. The code is designed specifically for this CAPTCHA style, but there’s no reason why the getImageData trick combined with a alternate OCR implementation couldn’t be used to solve for other systems. This is pretty fascinating stuff.

Is there a better (more convenient, harder to cheat) way to prove humanness? What else could you make in Javascript using OCR, neural nets, or per-pixel image processing?

Megaupload Auto-fill CAPTCHA

MuCaptcha Online Demo

OCR and Neural Nets in JavaScript – John Resig

Internet Dereams is a clean, user friendly and attractive Admin template that would fit in perfectly as the backend for most web applications. Included in the template are the login screens, the dashboard, form elements and table layout screens. The PSD is also available.

Internet Dreams Admin Skin
Internet Dereams is a clean, user friendly and attractive Admin template that would fit in perfectly as the backend for most web applications. Included in the template are the login screens, the dashboard, form elements and table layout screens. The PSD is also available.
admintemplate_01
Internet Dreams Admin Skin →
View Screenshots →
Continue reading “Top 10 template-html free for Admin-Backend Full PSD” »

Kế thừa với prototypeNếu như các bạn đã từng tìm hiểu về kế thừa với JavaScript thì hẳn các bạn nhận ra rằng có khá nhiều cách để cài đặt, tuy nhiên trong bài viết này tôi sẽ chỉ giới thiệu một cách mà theo cá nhân là khá đơn giản và tiện lợi khi triển khai, đó là sử dụng prototype và constructor.Trước hết, giả sử chúng ta có hai class ParentClass và ChildClass. Để thực hiện cho ChildClass kế thừa ParentClass ta lần lượt các bước sau:Cho prototype của ChildClass là một thể hiện của ParentClass:ChildClass.prototype=new ParentClass();Cài đặt lại thuộc tính constructor cho ChildClass: ChildClass.prototype.constructor=ChildClass;Như vậy với hai bước đơn giản ta đã thực hiện được kế thừa trong JavaScript. Tuy nhiên còn khá nhiều vấn đề nảy sinh trong khi bạn xây dựng các class phức tạp, ví dụ như làm thế nào để gọi phương thức của ParentClass trong khi ChildClass đã overridden nó, hay vấn đề về virtual class tức là class chỉ có thể kế thừa mà không cho phép tạo một thể hiện cho nó. Chúng ta sẽ lần lượt giải quyết vấn đề này tiếp sau đây.Nhưng trước khi đi vào các vấn đề đã nêu ta hãy làm một ví dụ thú vị sau:
Code:
//Class Động vật có vúfunction Mammal(name){this.name=name;    this.offspring=[];//Mùa sinh sản!!!}//Phương thức sinh con (hoặc có con)Mammal.prototype.haveABaby=function(){    var newBaby=new Mammal("Baby "+this.name); this.offspring.push(newBaby);    return newBaby;}//Hàm trả về tên con vậtMammal.prototype.toString=function(){    return '[Mammal "'+this.name+'"]';}//Class Mèo kế thừa Class Động vật có vúCat.prototype = new Mammal();Cat.prototype.constructor=Cat;//Constructor của class Catfunction Cat(name){    this.name=name;}//Hàm trả về tên con vậtCat.prototype.toString=function(){    return '[Cat "'+this.name+'"]';}//Tạo Mr.Bill !!!var someAnimal = new Mammal('Mr. Bill');//Tạo mèo Tomvar myPet = new Cat('Tom');alert('someAnimal is '+someAnimal);//Trả về 'someAnimal is [Mammal "Mr. Bill"]' alert('myPet is '+myPet);//Trả về 'myPet is [Cat "Tom"]'//Cho mèo sinh con (kế thừa từ Mammal)myPet.haveABaby();//Thông báo về số con của mèo Tomalert(myPet.offspring.length);alert(myPet.offspring[0]);//Trả về [Mammal "Baby Tom"]'

Vấn đề Super & Sub ClassHãy thử mở rộng ví dụ trên để ta có dịp minh họa cách mà một class con gọi đến một phương thức của class cha trong khi nó đã được overridden. Ta sẽ muốn rằng ngay sau khi mèo con được sinh ra nó sẽ kêu một tiếng “meeoo!” chẳng hạn. Để làm được điều này ta sẽ viết một hàm haveBaby của riêng class Cat trong đó sẽ gọi lại hàm haveBaby trong class Mammal:Cat.prototype.haveABaby=function(){Mammal.prototype.haveABaby.call(this);alert(“mew!”);}Ở đây, các bạn hãy nhớ lại cách thức sử dụng phương thức call của đối tượng Function mà ta đã từng đề cập. Như vậy với việc sử dụng call() ta hoàn toàn có thể làm được giống như phương thức “super()” trong Java và các ngôn ngữ khác.Do vậy, từ bây giờ để cho tiện thì tại sao chúng ta không cài đặt luôn một “super” cho class của chúng ta. Làm điều đó không mấy phiền hà như sau:Cat.prototype=newMammal();Cat.prototype.constructor=Cat;Cat.prototype.parent=Mammal.prototype;//”super”…Cat.prototype.haveABaby=function(){var theKitten = this.parent.haveABaby.call(this);//”super(this)”alert(“mew!”);return theKitten;}//Các bạn sẽ có thắc mắc nhỏ là tại sao không dùng từ super thay cho parent? Lí do là vì hình như JavaScript có ý định sài từ này trong các phiên bản tương lai thì phải! Một điều nữa nếu bạn băn khoăn là từ parent đã được DOM sử dụng khi truy cập đến các node, điều này thì cứ vô tư đi vì đây là JavaScript mà!!!:DVấn đề virtual ClassMột số ngôn ngữ lập trình hướng đối tượng có giải quyêt vấn đề về virtual class, tức là một class không thể có một thể hiện của chính nó, nhưng có thể kế thừa từ nó. Như trong ví dụ trên, ta muốn thêm vào một class LivingThing mà Mammal sẽ kế thừa từ nó, nhưng ta không muốn ai đó lại có thể tạo ra một LivingThing không mong muốn (chẳng hạn LivingStone!!:P). Với JavaScript ta có thể thực hiện điều này bằng cách thay thế function bằng một object cho virtual class.//Khai báo class kiểu JSONLivingThing={beBorn : function(){this.alive=true;}}//…Mammal.prototype = LivingThing;Mammal.prototype.parent = LivingThing;//Để ý rằng không phải là ‘LivingThing.prototype’Mammal.prototype.haveABaby=function(){this.parent.beBorn.call(this);var newBaby=new this.constructor(“Baby “+this.name);this.offspring.push(newBaby);return newBaby;}Như vậy nếu một ai đó khai báo như sau:var stone= new LivingThing(); // Sẽ gây lỗiBởi vì LivingThing bây giờ không phải là kiểu function mà có kiểu là object, do đó không thể coi nó như là một constructor với từ khóa new.Như các bạn đã thấy, với cách cài đặt kế thừa trên ta luôn phải thực hiện hai dòng lệnh bắt buộc mỗi khi thực hiện kế thừa. Để cho tiện lợi, ta có thể mở rộng khả năng này cho bản thân object Function trong JavaScript, và coi đó như là một thuộc tính vốn có của BLOCKED SCRIPT

Code:
 Function.prototype.inheritsFrom=function(parentClsOrObj){        if (parentClsOrObj.constructor == Function ){            //Normal Inheritance            this.prototype = new parentClsOrObj;            this.prototype.constructor = this;            this.prototype.parent=parentClsOrObj.prototype;        }        else        {            //Pure Virtual Inheritance            this.prototype = parentClsOrObj;            this.prototype.constructor = this;            this.prototype.parent = parentClsOrObj;        }        return this;    }    //    //    LivingThing = {        beBorn : function(){            this.alive = true;        }    }    //    //    function Mammal(name){        this.name=name;        this.offspring=[];    }    Mammal.inheritsFrom( LivingThing );    Mammal.prototype.haveABaby=function(){        this.parent.beBorn.call(this);        var newBaby=new this.constructor( "Baby "+this.name);        this.offspring.push(newBaby);        return newBaby;    }    //    //    function Cat( name ){        this.name=name;    }    Cat.inheritsFrom( Mammal );    Cat.prototype.haveABaby=function(){        var theKitten = this.parent.haveABaby.call(this);        alert("mew!");        return theKitten;    }    Cat.prototype.toString=function(){        return '[Cat "'+this.name+'"]';    }    //    //    var tom = new Cat( "Tom" );    var kitten = tom.haveABaby( ); // mew!    alert( kitten ); // [Cat "Baby Tom"]

Class và prototypeTrong lập trình hướng đối tượng, chúng ta thường tạo những đối tượng từ các lớp (class), trong đó các object được coi như là trường hợp cụ thể của một lớp.Trong javascript bạn có thể định nghĩa các thuộc tính và phương thức sau khi nó được khởi tạo.Ví dụ:

Code:
var oCar = new Object;oCar.color = “red”;oCar.doors = 4;oCar.mpg = 23;oCar.showColor = function () {alert(this.color);};

Nhưng đoạn mã trên chỉ cho việc bạn khởi tạo 1 đối tượng bất kỳ, không cụ thể là 1 phương thức khởi tạo của 1 đối tượng nào đó.Phương thức khởi tạoTrong javascript, tên hàm khởi tạo cũng chính là tên lớp. Nó bắt đầu bằng 1 ký tự hoa.

Code:
function Car(sColor, iDoors, iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.showColor = function () {alert(this.color)};}var oCar1 = new Car(“red”, 4, 23);var oCar2 = new Car(“blue”, 3, 25);

Mẫu prototypeMẫu prototype cho phép bạn định nghĩa thêm phương thức khởi tạo của 1 class sau khi phương thức khởi tạo đã được định nghĩa.

Code:
function Car() {}Car.prototype.color = “red”;Car.prototype.doors = 4;Car.prototype.mpg = 23;Car.prototype.showColor = function () {alert(this.color);};var oCar1 = new Car();var oCar2 = new Car();

Private & publicHầu hết các ngôn ngữ lập trình hướng đối tượng quen thuộc như Java hay C# đều hỗ trợ từ khóa public và private cho các thuộc tính cũng như phương thức trong class. Với JavaScript chúng ta cũng có thể tạo ra các pattern để giả lập hai từ khóa này trong các class (cũng giả lập luôn!!):Private variables: những biến được khai báo với từ khóa var bên trong object, chỉ có thể được truy nhập bởi các hàm riêng (private functions) hoặc các phương thức đặc quyền(privileged methods) của object.Private functions: những hàm được khai báo kiểu inline hoặc khai báo kiểu var functionName=function(){…} và được truy cập bởi các phương thức đặc quyền bên trong object.Privileged methods: những hàm được khai báo kiểu this.methodName=function(){…} bên trong object. Những hàm này có thể được gọi bên ngoài tới object.Public property: là những thuộc tính được khai báo kiểu this.propertyName, những thuộc tính này có thể thay đổi từ bên ngoài của object.Public method: là những phương thức được khai báo kiểu ClassName.prototype.methodName=function(){…}, những phương thức này có thể được gọi từ bên ngoài object.Static property: những thuộc tính được khai báo kiểu ClassName.propertyName=someValue.Prototype property: những thuộc tính được khai báo kiểu ClassName.prototype.propertyName=someValue.Hoặc chúng ta có thể xây đựng một cách đơn giản theo các Pattern dưới đây:

Code:
 //Public:function Constructor(...) {    this.membername = value;}Constructor.prototype.membername = value;    //Private:function Constructor(...) {var that = this;var membername = value;function membername(...) {...}}

//chú ýfunction membername(…) {…}//có thể thay thế chovar membername = function membername(…) {…};//Privilegedfunction Constructor(…) {this.membername = function (…) {…};}

Remedial JavaScript

The JavaScript Programming Language suffers from premature standardization. It was rushed to market and then instantly had a huge user base and, soon after, a formal international standard. There was no time during its development to polish the language. As a result, it still has some rough spots.Some of the problems we can easily avoid by not using misfeatures like the with statement. A lint program can be helpful in keeping us clear of some of the sharp edges.Some feature omissions can be corrected by adding new functions and basic methods to our standard programming toolkit. That is what we will be doing here. There are functions that I feel should have been in the Standard and required in every implementation. Fortunately, JavaScript is such an expressive language that we can easily fix the omissions locally.JavaScript is most used in web applications, and there is still an incompatibility legacy left over from the Browser Wars. For a time, Netscape and Microsoft were frantically adding features to their browsers, sometimes imitating each other, sometimes planting proprietary hooks, sometimes incorrectly anticipating a future ECMAScript Language Specification.

Type Detection

Since JavaScript is a loosely-typed language, it is sometimes necessary to examine a value to determine its type. (This is sometimes necessary in strongly typed languages as well.) JavaScript provides a typeof operator to facilitate this, but typeof has problems.

Object 'object'
Array 'object'
Function 'function'
String 'string'
Number 'number'
Boolean 'boolean'
null 'object'
undefined 'undefined'

typeof [] produces 'object' instead of 'array'. That isn’t totally wrong since arrays in JavaScript inherit from objects, but it isn’t very useful. typeof null produces 'object' instead of 'null'. That is totally wrong.We can correct this by defining our own typeOf function, which we can use in place of the defective typeof operator.

isEmpty(v)

isEmpty(v) returns true if v is an object containing no enumerable members.

String Methods

JavaScript provides some useful methods for strings, but leaves out some important ones. Fortunately, JavaScript allows us to add new methods to the basic types.

entityify()

entityify() produces a string in which '<', '>', and '&' are replaced with their HTML entity equivalents. This is essential for placing arbitrary strings into HTML texts. So,

"if (a < b && b > c) {".entityify()

produces

"if (a &lt; b &amp;&amp; b &gt; c) {"

quote()

quote() produces a quoted string. This method returns a string that is like the original string except that it is wrapped in quotes and all quote and backslash characters are preceded with backslash.

supplant(object)

supplant() does variable substitution on the string. It scans through the string looking for expressions enclosed in { } braces. If an expression is found, use it as a key on the object, and if the key has a string value or number value, it is substituted for the bracket expression and it repeats. This is useful for automatically fixing URLs. So

param = {domain: 'valvion.com', media: 'http://media.valvion.com/'};url = "{media}logo.gif".supplant(param);

produces a url containing "http://media.valvion.com/logo.gif".

trim()

The trim() method removes whitespace characters from the beginning and end of the string.

Deployment

You can put these functions in your code library and copy them individually into your projects as you need them. Or you can put them all in a single file that you include in all of your projects, so you can always count on having a familiar platform to work from. Be sure to process the file with JSMin in order to reduce download time. You may have useful toolkit functions of your own to include.

Source

In the source code that follows, the priorities were portability and compactness.

function typeOf(value) {    var s = typeof value;    if (s === 'object') {        if (value) {            if (value instanceof Array) {                s = 'array';            }        } else {            s = 'null';        }    }    return s;}

The typeOf function above will only recognize arrays that are created in the same context (or window or frame). JavaScript does not provide an infallible mechanism for distinguishing arrays from objects, so if we want to recognize arrays that are constructed in a different frame, then we need to do something more complicated.

function typeOf(value) {    var s = typeof value;    if (s === 'object') {        if (value) {            if (typeof value.length === 'number' &&                    !(value.propertyIsEnumerable('length')) &&                    typeof value.splice === 'function') {                s = 'array';            }        } else {            s = 'null';        }    }    return s;}function isEmpty(o) {    var i, v;    if (typeOf(o) === 'object') {        for (i in o) {            v = o[i];            if (v !== undefined && typeOf(v) !== 'function') {                return false;            }        }    }    return true;}String.prototype.entityify = function () {    return this.replace(/&/g, "&amp;").replace(/</g,        "&lt;").replace(/>/g, "&gt;");};String.prototype.quote = function () {    var c, i, l = this.length, o = '"';    for (i = 0; i < l; i += 1) {        c = this.charAt(i);        if (c >= ' ') {            if (c === '\\' || c === '"') {                o += '\\';            }            o += c;        } else {            switch (c) {            case '\b':                o += '\\b';                break;            case '\f':                o += '\\f';                break;            case '\n':                o += '\\n';                break;            case '\r':                o += '\\r';                break;            case '\t':                o += '\\t';                break;            default:                c = c.charCodeAt();                o += '\\u00' + Math.floor(c / 16).toString(16) +                    (c % 16).toString(16);            }        }    }    return o + '"';};String.prototype.supplant = function (o) {    return this.replace(/{([^{}]*)}/g,        function (a, b) {            var r = o[b];            return typeof r === 'string' || typeof r === 'number' ? r : a;        }    );};String.prototype.trim = function () {    return this.replace(/^\s+|\s+$/g, "");};

Classical Inheritance in JavaScript

JavaScript is a class-free, object-oriented language, and as such, it uses prototypal inheritance instead of classical inheritance. This can be puzzling to programmers trained in conventional object-oriented languages like C++ and Java. JavaScript’s prototypal inheritance has more expressive power than classical inheritance, as we will see presently.Java JavaScript

Strongly-typed Loosely-typed
Static Dynamic
Classical Prototypal
Classes Functions
Constructors Functions
Methods Functions

But first, why do we care about inheritance at all? There are primarily two reasons. The first is type convenience. We want the language system to automatically cast references of similar classes. Little type-safety is obtained from a type system which requires the routine explicit casting of object references. This is of critical importance in strongly-typed languages, but it is irrelevant in loosely-typed languages like JavaScript, where object references never need casting.The second reason is code reuse. It is very common to have a quantity of objects all implementing exactly the same methods. Classes make it possible to create them all from a single set of definitions. It is also common to have objects that are similar to some other objects, but differing only in the addition or modification of a small number of methods. Classical inheritance is useful for this but prototypal inheritance is even more useful.To demonstrate this, we will introduce a little sugar which will let us write in a style that resembles a conventional classical language. We will then show useful patterns which are not available in classical languages. Then finally, we will explain the sugar.

Classical Inheritance

First, we will make a Parenizor class that will have set and get methods for its value, and a toString method that will wrap the value in parens.

function Parenizor(value) {
   this.setValue(value);
}
Parenizor.method('setValue', function (value) {
    this.value = value;
    return this;
});
Parenizor.method('getValue', function () {
    return this.value;
});
Parenizor.method('toString', function () {
    return '(' + this.getValue() + ')';
});

The syntax is a little unusual, but it is easy to recognize the classical pattern in it. The method method takes a method name and a function, adding them to the class as a public method.So now we can write

myParenizor = new Parenizor(0);
myString = myParenizor.toString();

As you would expect, myString is "(0)".Now we will make another class which will inherit from Parenizor, which is the same except that its toString method will produce "-0-" if the value is zero or empty.

function ZParenizor(value) {
    this.setValue(value);
}
ZParenizor.inherits(Parenizor);
ZParenizor.method('toString', function () {
    if (this.getValue()) {
        return this.uber('toString');
    }
    return "-0-";
});

The inherits method is similar to Java’s extends. The uber method is similar to Java’s super. It lets a method call a method of the parent class. (The names have been changed to avoid reserved word restrictions.)So now we can write

myZParenizor = new ZParenizor(0);
myString = myZParenizor.toString();

This time, myString is "-0-".JavaScript does not have classes, but we can program as though it does.

Multiple Inheritance

By manipulating a function’s prototype object, we can implement multiple inheritance, allowing us to make a class built from the methods of multiple classes. Promiscuous multiple inheritance can be difficult to implement and can potentially suffer from method name collisions. We could implement promiscuous multiple inheritance in JavaScript, but for this example we will use a more disciplined form called Swiss Inheritance.Suppose there is a NumberValue class that has a setValue method that checks that the value is a number in a certain range, throwing an exception if necessary. We only want its setValue and setRange methods for our ZParenizor. We certainly don’t want its toString method. So, we write

ZParenizor.swiss(NumberValue, 'setValue', 'setRange');

This adds only the requested methods to our class.

Parasitic Inheritance

There is another way to write ZParenizor. Instead of inheriting from Parenizor, we write a constructor that calls the Parenizor constructor, passing off the result as its own. And instead of adding public methods, the constructor adds privileged methods.

function ZParenizor2(value) {
    var that = new Parenizor(value);
    that.toString = function () {
        if (this.getValue()) {
            return this.uber('toString');
        }
        return "-0-"
    };
    return that;
}

Classical inheritance is about the is-a relationship, and parasitic inheritance is about the was-a-but-now’s-a relationship. The constructor has a larger role in the construction of the object. Notice that the uber née super method is still available to the privileged methods.

Class Augmentation

JavaScript’s dynamism allows us to add or replace methods of an existing class. We can call the method method at any time, and all present and future instances of the class will have that method. We can literally extend a class at any time. Inheritance works retroactively. We call this Class Augmentation to avoid confusion with Java’s extends, which means something else.

Object Augmentation

In the static object-oriented languages, if you want an object which is slightly different than another object, you need to define a new class. In JavaScript, you can add methods to individual objects without the need for additional classes. This has enormous power because you can write far fewer classes and the classes you do write can be much simpler. Recall that JavaScript objects are like hashtables. You can add new values at any time. If the value is a function, then it becomes a method.So in the example above, I didn’t need a ZParenizor class at all. I could have simply modified my instance.

myParenizor = new Parenizor(0);
myParenizor.toString = function () {
    if (this.getValue()) {
        return this.uber('toString');
    }
    return "-0-";
};
myString = myParenizor.toString();

We added a toString method to our myParenizor instance without using any form of inheritance. We can evolve individual instances because the language is class-free.

Sugar

To make the examples above work, I wrote four sugar methods. First, the method method, which adds an instance method to a class.

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

This adds a public method to the Function.prototype, so all functions get it by Class Augmentation. It takes a name and a function, and adds them to a function’s prototype object.It returns this. When I write a method that doesn’t need to return a value, I usually have it return this. It allows for a cascade-style of programming.Next comes the inherits method, which indicates that one class inherits from another. It should be called after both classes are defined, but before the inheriting class’s methods are added.

Function.method('inherits', function (parent) {
    var d = {}, p = (this.prototype = new parent());
    this.method('uber', function uber(name) {
        if (!(name in d)) {
            d[name] = 0;
        }
                var f, r, t = d[name], v = parent.prototype;
        if (t) {
            while (t) {
                v = v.constructor.prototype;
                t -= 1;
            }
            f = v[name];
        } else {
            f = p[name];
            if (f == this[name]) {
                f = v[name];
            }
        }
        d[name] += 1;
        r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
        d[name] -= 1;
        return r;
    });
    return this;
});

Again, we augment Function. We make an instance of the parent class and use it as the new prototype. We also correct the constructor field, and we add the uber method to the prototype as well.The uber method looks for the named method in its own prototype. This is the function to invoke in the case of Parasitic Inheritance or Object Augmentation. If we are doing Classical Inheritance, then we need to find the function in the parent‘s prototype. The return statement uses the function’s apply method to invoke the function, explicitly setting this and passing an array of parameters. The parameters (if any) are obtained from the arguments array. Unfortunately, the arguments array is not a true array, so we have to use apply again to invoke the array slice method.Finally, the swiss method.

Function.method('swiss', function (parent) {
    for (var i = 1; i < arguments.length; i += 1) {
        var name = arguments[i];
        this.prototype[name] = parent.prototype[name];
    }
    return this;
});

The swiss method loops through the arguments. For each name, it copies a member from the parent‘s prototype to the new class’s prototype.

Conclusion

JavaScript can be used like a classical language, but it also has a level of expressiveness which is quite unique. We have looked at Classical Inheritance, Swiss Inheritance, Parasitic Inheritance, Class Augmentation, and Object Augmentation. This large set of code reuse patterns comes from a language which is considered smaller and simpler than Java.Classical objects are hard. The only way to add a new member to a hard object is to create a new class. In JavaScript, objects are soft. A new member can be added to a soft object by simple assignment.Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies. Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.I have been writing JavaScript for 8 years now, and I have never once found need to use an uber function. The super idea is fairly important in the classical pattern, but it appears to be unnecessary in the prototypal and functional patterns. I now see my early attempts to support the classical model in JavaScript as a mistake.

Prototypal Inheritance in JavaScript

Five years ago I wrote Classical Inheritance in JavaScript. It showed that JavaScript is a class-free, prototypal language, and that it has sufficient expressive power to simulate a classical system. My programming style has evolved since then, as any good programmer’s should. I have learned to fully embrace prototypalism, and have liberated myself from the confines of the classical model.My journey was circuitous because JavaScript itself is conflicted about its prototypal nature. In a prototypal system, objects inherit from objects. JavaScript, however, lacks an operator that performs that operation. Instead it has a new operator, such thatnew f()produces a new object that inherits fromf.prototypeThis indirection was intended to make the language seem more familiar to classically trained programmers, but failed to do that, as we can see from the very low opinion Java programmers have of JavaScript. JavaScript’s constructor pattern did not appeal to the classical crowd. It also obscured JavaScript’s true prototypal nature. As a result, there are very few programmers who know how to use the language effectively.Fortunately, it is easy to create an operator that implements true prototypal inheritance. It is a standard feature in my toolkit, and I highly recommend it for yours.
    function object(o) {        function F() {}        F.prototype = o;        return new F();    }

The object function untangles JavaScript’s constructor pattern, achieving true prototypal inheritance. It takes an old object as a parameter and returns an empty new object that inherits from the old one. If we attempt to obtain a member from the new object, and it lacks that key, then the old object will supply the member. Objects inherit from objects. What could be more object oriented than that?So instead of creating classes, you make prototype objects, and then use the object function to make new instances. Objects are mutable in JavaScript, so we can augment the new instances, giving them new fields and methods. These can then act as prototypes for even newer objects. We don’t need classes to make lots of similar objects.For convenience, we can create functions which will call the object function for us, and provide other customizations such as augmenting the new objects with privileged functions. I sometimes call these maker functions. If we have a maker function that calls another maker function instead of calling the object function, then we have a parasitic inheritance pattern.I have found that by using these tools, coupled with JavaScript’s lambdas and object quasi-literals, I can write well-structured programs that are large, complex, and efficient. The classical object model is by far the most popular today, but I think that the prototypal object model is more capable and offers more expressive power.Learning these new patterns also made me a better classical programmer. Insights from the dynamic world can have application in the static.2006-06-07Here is another formulation:

Object.prototype.begetObject = function () {    function F() {}    F.prototype = this;    return new F();};newObject = oldObject.begetObject();

2007-04-02The problem with the object function is that it is global, and globals are clearly problematic. The problem with Object.prototype.begetObject is that it trips up incompetent programs, and it can produce unexpected results when begetObject is overridden.So I now prefer this formulation:

if (typeof Object.create !== 'function') {    Object.create = function (o) {        function F() {}        F.prototype = o;        return new F();    };}newObject = Object.create(oldObject);

2008-04-07

Scope in JavaScript

is one of the foundational aspects of the JavaScript language, and probably the one I’ve struggled with the most when building complex programs. I can’t count the number of times I’ve lost track of what the this keyword refers to after passing control around from function to function, and I’ve often found myself contorting my code in all sorts of confusing ways, trying to retain some semblance of sanity in my understanding of which variables were accessible where.
In typical object-oriented programming, we need a way of identifying and referring to the object that we’re currently working with. this serves the purpose admirably, providing our objects the ability to examine themselves, and point at their own properties.

This article will tackle the problem head-on, outlining definitions of context and scope, examining two JavaScript methods that allow us to manipulate context, and concluding with a deep dive into an effective solution to ninety percent of the problems I’ve run into.

Where Am I? And Who Are You?

Every bit of your JavaScript program is executed in one execution context or another. You can think of these contexts as your code’s neighborhood, giving each line an understanding of where it comes from, and who its friends and neighbors are. As it turns out, this is important information, as JavaScript societies have fairly strict rules about who can associate with whom; execution contexts are better thought of as gated communities than as open subdivisions.We can refer to these social boundaries generally as scope, and they’re important enough to be codified in each neighborhood’s charter, which we’ll refer to as the context’s scope chain. Code within a particular neighborhood can only access variables listed on its scope chain, and prefers interaction with locals to associations outside its neighborhood.Practically speaking, evaluating a function establishes a distinct execution context that appends its local scope to the scope chain it was defined within. JavaScript resolves identifiers within a particular context by climbing up the scope chain, moving locally to globally. This means that local variables with the same name as variables higher up on the scope chain take precedence, which makes sense: If my good friends are talking together about “Mike West,” it’s pretty clear that they’re talking about me, not about the bluegrass singer or the Duke professor, even though the latter two are (arguably) better known.Let’s walk through some example code to explore the implications:<script type="text/javascript">var ima_celebrity = "Everyone can see me! I'm famous!",the_president = "I'm the decider!";function pleasantville() {var the_mayor = "I rule Pleasantville with an iron fist!",ima_celebrity = "All my neighbors know who I am!";function lonely_house() {var agoraphobic = "I fear the day star!",a_cat = "Meow.";}}</script> Our global star, ima_celebrity, is recognized by everyone. She’s politically active, talking with the_president on a fairly frequent basis, and incredibly friendly; she’ll sign autographs and answer questions for anyone she runs into. That said, she doesn’t have a whole lot of personal contact with her fans. She’s pretty sure they exist and that they probably have lives of their own somewhere, but she certainly doesn’t know what they’re doing, or even their names.Inside pleasantville, the_mayor is a well-known face. She’s always walking the streets of her town, chatting up her constituents, shaking hands, and kissing babies. As pleasantville is a big, important neighborhood, she’s got a big red phone in her office, giving her a direct line to the president (or at least a top aide) 24 hours a day, 7 days a week. She’s seen lonely_house up on a hill at the outskirts of town, but never really worried about who lives inside.That lonely_house is a world unto itself. The agoraphobic stays inside most of the time, playing solitaire and feeding a_cat. He’s called the_mayor a few times to ask about local noise regulations, and even wrote ima_celebrity (Pleasantville’s ima_celebrity, that is) some fan mail after seeing her on the local news.

this? What’s that?

In addition to establishing a scope chain, each execution context offers a keyword named this. In its most common usage, this serves as an identity function, providing our neighborhoods a way of referring to themselves. We can’t always rely on that behavior, however: Depending on how we get into a particular neighborhood, this might mean something else entirely. In fact, how we get into the neighborhood is itself exactly what this generally refers to. Four scenarios deserve special attention:

  • Calling an Object’s MethodIn typical object-oriented programming, we need a way of identifying and referring to the object that we’re currently working with. this serves the purpose admirably, providing our objects the ability to examine themselves, and point at their own properties. <script type="text/javascript">var deep_thought = {the_answer: 42,ask_question: function () {return this.the_answer;}};var the_meaning = deep_thought.ask_question();</script> This example builds an object named deep_thought, sets its the_answer property to 42, and creates an ask_question method. When deep_thought.ask_question() is executed, JavaScript establishes an execution context for the function call, setting this to the object referenced by whatever came before the last ”.”, in this case: deep_thought. The method can then look in the mirror via this to examine its own properties, returning the value stored in this.the_answer: 42.
  • ConstructorLikewise, when defining a function to be used as a constructor with the new keyword, this can be used to refer to the object being created. Let’s rewrite the example above to reflect that scenario: <script type="text/javascript">function BigComputer(answer) {this.the_answer = answer;this.ask_question = function () {return this.the_answer;}}var deep_thought = new BigComputer(42);var the_meaning = deep_thought.ask_question();</script> Instead of explicitly creating the deep_thought object, we’ll write a function to create BigComputer objects, and instantiate deep_thought as an instance variable via the new keyword. When new BigComputer() is executed, a completely new object is created transparently in the background. BigComputer is called, and its this keyword is set to reference that new object. The function can set properties and methods on this, which is transparently returned at the end of BigComputer’s execution.Notice, though, that deep_thought.the_question() still works just as it did before. What’s going on there? Why does this mean something different inside the_question than it does inside BigComputer? Put simply, we entered BigComputer via new, so this meant “the new object.” On the other hand, we entered the_question via deep_thought, so while we’re executing that method, this means “whatever deep_thought refers to”. this is not read from the scope chain as other variables are, but instead is reset on a context by context basis.
  • Function CallWhat if we just call a normal, everyday function without any of this fancy object stuff? What does this mean in that scenario? <script type="text/javascript">function test_this() {return this;}var i_wonder_what_this_is = test_this();</script> In this case, we weren’t provided a context by new, nor were we given a context in the form of an object to piggyback off of. Here, this defaults to reference the most global thing it can: for web pages, this is the window object.
  • Event HandlerFor a more complicated twist on the normal function call, let’s say that we’re using a function to handle an onclick event. What does this mean when the event triggers our function’s execution? Unfortunately, there’s not a simple answer to this question.If we write the event handler inline, this refers to the global window object: <script type="text/javascript">function click_handler() {alert(this); // alerts the window object}</script>...<button id='thebutton' onclick='click_handler()'>Click me!</button> However, when we add an event handler via JavaScript, this refers to the DOM element that generated the event. (Note: The event handling shown here is short and readable, but otherwise poor. Please use a real addEvent function instead.): <script type="text/javascript">function click_handler() {alert(this); // alerts the button DOM node}function addhandler() {document.getElementById('thebutton').onclick = click_handler;}window.onload = addhandler;</script>...<button id='thebutton'>Click me!</button>

Complications

Let’s run with that last example for a moment longer. What if instead of running click_handler, we wanted to ask deep_thought a question every time we clicked the button? The code for that seems pretty straightforward; we might try this:<script type="text/javascript">function BigComputer(answer) {this.the_answer = answer;this.ask_question = function () {alert(this.the_answer);}}function addhandler() {var deep_thought = new BigComputer(42),the_button = document.getElementById('thebutton');the_button.onclick = deep_thought.ask_question;}window.onload = addhandler;</script> Perfect, right? We click on the button, deep_thought.ask_question is executed, and we get back “42.” So why is the browser giving us undefined instead? What did we do wrong?The problem is simply this: We’ve passed off a reference to the ask_question method, which, when executed as an event handler, runs in a different context than when it’s executed as an object method. In short, the this keyword in ask_question is pointing at the DOM element that generated the event, not at a BigComputer object. The DOM element doesn’t have a the_answer property, so we’re getting back undefined instead of “42.” setTimeout exhibits similar behavior, delaying the execution of a function while at the same time moving it out into a global context.This issue crops up all over the place in our programs, and it’s a terribly difficult problem to debug without keeping careful track of what’s going on in all the corners of your program, especially if your object has properties that do exist on DOM elements or the window object.

Manipulating Context With .apply() and .call()

We really do want to be able to ask deep_thought a question when we click the button, and more generally, we do want to be able to call object methods in their native context when responding to things like events and setTimeout calls. Two little-known JavaScript methods, apply and call, indirectly enable this functionality by allowing us to manually override the default value of this when we execute a function call. Let’s look at call first:<script type="text/javascript">var first_object = {num: 42};var second_object = {num: 24};function multiply(mult) {return this.num * mult;}multiply.call(first_object, 5); // returns 42 * 5multiply.call(second_object, 5); // returns 24 * 5</script> In this example, we first define two objects, first_object and second_object, each with a num property. Then we define a multiply function that accepts a single argument, and returns the product of that argument, and the num property of its this object. If we called that function by itself, the answer returned would almost certainly be undefined, since the global window object doesn’t have a num property unless we explicitly set one. We need some way of telling multiply what its this keyword ought refer to; the call method of the multiply function is exactly what we’re looking for.The first argument to call defines what this means inside the executed function. The remaining arguments to call are passed into the executed function, just as if you’d called it yourself. So, when multiply.call(first_object, 5) is executed, the multiply function is called, 5 is passed in as the first argument, and the this keyword is set to refer to object first_object. Likewise, when multiply.call(second_object, 5) is executed, the multiply function is called, 5 is passed in as the first argument, and the this keyword is set to refer to object second_object.apply works in exactly the same way as call, but allows you to wrap up the arguments to the called function in an array, which can be quite useful when programatically generating function calls. Replicating the functionality we just talked about using apply is trivial:<script type="text/javascript">...multiply.apply(first_object, [5]); // returns 42 * 5multiply.apply(second_object, [5]); // returns 24 * 5</script> apply and call are very useful on their own, and well worth keeping around in your toolkit, but they only get us halfway to solving the problem of context shifts for event handlers. It’s easy to think that we could solve the problem by simply using call to shift the meaning of this when we set up the handler:function addhandler() {var deep_thought = new BigComputer(42),the_button = document.getElementById('thebutton');the_button.onclick = deep_thought.ask_question.call(deep_thought);} The problem with this line of reasoning is simple: call executes the function immediately. Instead of providing a function reference to the onclick handler, we’re giving it the result of an executed function. We need to exploit another feature of JavaScript to really solve this problem.

The Beauty of .bind()

I’m not a huge fan of the Prototype JavaScript framework, but I am very much impressed with the quality of its code as a whole. In particular, one simple addition it makes to the Function object has had a hugely positive impact on my ability to manage the context in which function calls execute: bind performs the same general task as call, altering the context in which a function executes. The difference is that bind returns a function reference that can be used later, rather than the result of an immediate execution that we get with call.If we simplify the bind function a bit to get at the key concepts, we can insert it into the multiplication example we discussed earlier to really dig into how it works; it’s quite an elegant solution:<script type="text/javascript">var first_object = {num: 42};var second_object = {num: 24};function multiply(mult) {return this.num * mult;}Function.prototype.bind = function(obj) {var method = this,temp = function() {return method.apply(obj, arguments);};return temp;}var first_multiply = multiply.bind(first_object);first_multiply(5); // returns 42 * 5var second_multiply = multiply.bind(second_object);second_multiply(5); // returns 24 * 5</script> First, we define first_object, second_object, and the multiply function, just as before. With those taken care of, we move on to creating a bind method on the Function object’s prototype, which has the effect of making bind available for all functions in our program. When multiply.bind(first_object) is called, JavaScript creates an execution context for the bind method, setting this to the multiply function, and setting the first argument, obj, to reference first_object. So far, so good.The real genius of this solution is the creation of method, set equal to this (the multiply function itself). When the anonymous function is created on the next line, method is accessible via its scope chain, as is obj (this couldn’t be used here, because when the newly created function is executed, this will be overwritten by a new, local context). This alias to this makes it possible to use apply to execute the multiply function, passing in obj to ensure that the context is set correctly. In computer-science-speak, temp is a closure that, when returned at the end of the bind call, can be used in any context whatsoever to execute multiply in the context of first_object.This is exactly what we need for the event handler and setTimeout scenarios discussed above. The following code solves that problem completely, binding the deep_thought.ask_question method to the deep_thought context, so that it executes correctly whenever the event is triggered:function addhandler() {var deep_thought = new BigComputer(42),the_button = document.getElementById('thebutton');the_button.onclick = deep_thought.ask_question.bind(deep_thought);} Beautiful.

References

  • JavaScript Closures is the best resource on the net for a thorough discussion of closures: what they do, how they do it, and how to use them without going insane.
  • The Protype JavaScript Framework is full of little nuggets like bind. The version available here not only allows the binding of a particular this value, but also of some or all of a function’s arguments, which comes in handy all too often.
  • Douglas Crockford’s JavaScript essays are excellent resources for both basic and advanced JavaScript programmers. The man knows what he’s talking about, and explains difficult concepts in an easy-to-grasp manner.
  • Variable Scope for New Programmers is a good article if you’d like more discussion of scope from a beginner’s perspective. Written by Jonathan Snook, and published in this very magazine at the end of last year, it’s still an informative and useful read.

Overview

This document is an introduction to the JavaScript Programming Language for professional programmers. It is a small language, so if you are familiar with other languages, then this won’t be too demanding.JavaScript is not Java. They are two very different languages. JavaScript is not a subset of Java. It is not interpreted Java. (Java is interpreted Java!) JavaScript shares C-family syntax with Java, but at a deeper level it shows greater similarity to the languages Scheme and Self. It is a small language, but it is also a suprisingly powerful and expressive language.You should take a look at it. You will find that it is not a toy language, but a full programming language with many distinctive properties.JavaScript is a regular language which won’t take much time to learn. It is better suited to some tasks, such as client programming, than Java is. In my own practice, I have found that working with JavaScript has made me a better Java programmer because it introduced me to a useful set of dynamic techniques.When JavaScript was first introduced, I dismissed it as being not worth my attention. Much later, I took another look at it and discovered that hidden in the browser was an excellent programming language. My initial attitudes were based on the initial positioning of JavaScript by Sun and Netscape. They made many misstatements about JavaScript in order to avoid positioning JavaScript as a competitor to Java. Those misstatements continue to echo in the scores of badly written JavaScript books aimed at the dummies and amateurs market.

History

JavaScript was developed by Brendan Eich at Netscape as the in-page scripting language for Navigator 2. It is a remarkably expressive dynamic programming language. Because of its linkage to web browsers, it instantly became massively popular. It never got a trial period in which it could be corrected and polished based on actual use. The language is powerful and flawed.This document describes ECMAScript Edition 3 (aka JavaScript 1.5). Microsoft and Netscape are developing a static revision which does not correct the language’s flaws. That new language is not JavaScript and is beyond the scope of this document.

Data Types

JavaScript contains a small set of data types. It has the three primitive types boolean, number, and string and the special values null and undefined. Everything else is variations on the object type.Boolean has two values: true and false.Number is 64-bit floating point, similar to Java’s double and Double. There is no integer type. Division between two integers may produce a fractional result. Number also includes the special values NaN (not a number) and Infinity.String is a sequence of zero or more Unicode characters. There is no separate character type. A character is represented as a string of length 1. Literal strings are quoted using the ' or " characters. The quote characters can be used interchangeably, but they have to match.

'This is a string.'
"Isn't this a string? Yes!"
'A' // The character A
"" // An empty string

Escapement is done with the \ character, like in Java. Strings are immutable. Strings have a length member which is used to determine the number of characters in the string.

var s = "Hello World!";s.length == 12

It is possible to add methods to the simple types. So, for example, you can add an int() method to all numbers, so that Math.PI.int() produces 3.An implementation may provide other types, such as Dates and Regular Expressions, but these are really just objects. Everything else is just objects.

Objects

JavaScript has very nice notational conveniences for manipulating hashtables.

var myHashtable = {};

This statement makes a new hashtable and assigns it to a new local variable. JavaScript is loosely typed, so we don’t use type names in declarations. We use subscript notation to add, replace, or retrieve elements in the hashtable.

myHashtable["name"] = "Carl Hollywood";

There is also a dot notation which is a little more convenient.

myHashtable.city = "Anytown";

The dot notation can be used when the subscript is a string constant in the form of a legal identifier. Because of an error in the language definition, reserved words cannot be used in the dot notation, but they can be used in the subscript notation.You can see that JavaScript’s hashtable notation is very similar to Java’s object and array notations. JavaScript takes this much farther: objects and hashtables are the same thing, so I could have written

var myHashtable = new Object();

and the result would have been exactly the same.There is an enumeration capability built into the for statement.

for (var n in myHashtable) {    if (myHashtable.hasOwnProperty(n)) {        document.writeln("<p>" + n + ": " + myHashtable[n] + "</p>");    }}

The result will be

<p>name: Carl Hollywood</p><p>city: Anytown</p>

An object is a referenceable container of name/value pairs. The names are strings (or other elements such as numbers that are converted to strings). The values can be any of the data types, including other objects. Objects are usually implemented as hash-tables, but none of the hash-table nature (such as hash functions or rehashing methods) is visible.Objects can easily be nested inside of other objects, and expressions can reach into the inner objects.

this.div = document.body.children[document.body.children.length - 1];

In the object literal notation, an object description is a set of comma-separated name/value pairs inside curly braces. The names can be identifiers or strings followed by a colon. Because of an error in the language definition, reserved words cannot be used in the identifier form, but they can be used in the string form. The values can be literals or expressions of any type.

var myObject = {name: "Jack B. Nimble", 'goto': 'Jail', grade: 'A', level: 3};
return {    event: event,    op: event.type,    to: event.srcElement,    x: event.clientX + document.body.scrollLeft,    y: event.clientY + document.body.scrollTop};
emptyObject = {};

JavaScript’s object literals are the basis of the JSON data interchange format.New members can be added to any object at any time by assignment.

myObject.nickname = 'Jackie the Bee';

Arrays and functions are implemented as objects.

Arrays

Arrays in JavaScript are also hashtable objects. This makes them very well suited to sparse array applications. When you construct an array, you do not need to declare a size. Arrays grow automatically, much like Java vectors. The values are located by a key, not by an offset. This makes JavaScript arrays very convenient to use, but not well suited for applications in numerical analysis.The main difference between objects and arrays is the length property. The length property is always 1 larger than the largest integer key in the array. There are two ways to make a new array:

var myArray = [];var myArray = new Array();

Arrays are not typed. They can contain numbers, strings, booleans, objects, functions, and arrays.You can mix strings and numbers and objects in the same array. You can use arrays as general nested sequences, much as s-expressions. The first index in an array is usually zero.When a new item is added to an array and the subscript is an integer that is larger than the current value of length, then the length is changed to the subscript plus one. This is a convenience feature that makes it easy to use a for loop to go through the elements of an array.Arrays have a literal notation, similar to that for objects.

myList = ['oats', 'peas', 'beans', 'barley'];emptyArray = [];month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];slides = [    {url: 'slide0001.html', title: 'Looking Ahead'},    {url: 'slide0008.html', title: 'Forecast'},    {url: 'slide0021.html', title: 'Summary'}];

A new item can be added to an array by assignment.

a[i + j] = f(a[i], a[j]);

Functions

Functions in JavaScript look like C functions, except that they are declared with the function keyword instead of a type. When calling a function, it is not required that you pass a fixed number of parameters. Excess parameters are ignored. Missing parameters are given the value undefined. This makes it easy to write functions that deal with optional arguments.A function has access to an arguments array. It contains all of the parameters that were actually sent by the caller. It makes it easy to deal with functions taking a variable number of arguments. For example,

function sum() {  // Take any number of parameters and return the sum    var total = 0;    for (var i = 0; i < arguments.length; ++i) {        total += arguments[i];    }    return total;}

JavaScript has inner functions, which serve the same purpose as inner classes in Java, but are much lighter. JavaScript also has anonymous functions, which act as lambda expressions. Functions have lexical scoping.Functions are first class objects in JavaScript. That means that they can be stored in objects and passed as arguments to functions.

Definition

There are three notations for defining functions: function statement, function operator, and function constructor.

Function statement

The function statement creates a named function within the current scope.

function name(argumentlist) block

Functions can be nested. See Closures. An argumentlist is zero or more argument names, separated with commas. A block is a list of zero or more statements enclosed in { }.The function statement is a shorthand for the function operator form:

var name = function name (argumentlist) block ;

Function operator

The function operator is a prefix operator that produces a function object. It looks similar to the function statement.

function name(argumentlist) block

The name is optional. If it is provided, then it can be used by the function body to call itself recursively. It can also be used to access the function’s object members (except on IE). If the name is omitted, then it is an anonymous function.The function operator is commonly used to assign functions to a prototype.The function operator can also be used to define functions in-place, which is handy when writing callbacks.

Function constructor

The function constructor takes strings containing the arguments and body, and produces a function object.

new Function(strings)

Do not use this form. The quoting conventions of the language make it very difficult to correctly express a function body as a string. In the string form, early error checking cannot be done. It is slow because the compiler must be invoked every time the constructor is called. And it is wasteful of memory because each function requires its own independent implementation.

Objects and this

A function is an object. It can contain members just as other objects. This allows a function to contain its own data tables. It also allows an object to act as a class, containing a constructor and a set of related methods.A function can be a member of an object. When a function is a member of an object, it is called a method. There is a special variable, called this that is set to the object when a method of the object is called.For example, in the expression foo.bar(), the this variable is set to the object foo as a sort of extra argument for the function bar. The function bar can then refer to this to access the object of interest.In a deeper expression like do.re.mi.fa(), the this variable is set to the object do.re.mi, not to the object do. In a simple function call, this is set to the Global Object (aka window), which is not very useful. The correct behavior should have been to preserve the current value of this, particularly when calling inner functions.

Constructor

Functions which are used to initialize objects are called constructors. The calling sequence for a constructor is slightly different than for ordinary functions. A constructor is called with the new prefix:

new Constructor(parameters…)

By convention, the name of a constructor is written with an initial capital.The new prefix changes the meaning of the this variable. Instead of its usual value, this will be the new object. The body of the constructor function will usually initialize the object’s members. The constructor will return the new object, unless explicitly overridden with the return statement.The constructed object will contain a secret prototype link field, which contains a reference to the constructor’s prototype member.

Prototype

Objects contain a hidden link property. This link points to the prototype member of the constructor of the object.When items are accessed from an object by the dot notation or the subscript notation, if the item is not found in the object then the link object is examined. If it is not found in the link object, and if the link object itself has a link object, then that link object is examined. If the chain of link objects is exhausted, then undefined is returned.This use of prototype link chains provides a sort of inheritance.Members can be added to the prototype by assignment. Here we define a new class Demo, which inherits from class Ancestor, and adds its own method foo.

function Demo() {}Demo.prototype = new Ancestor();Demo.prototype.foo = function () {};

Vars

Named variables are defined with the var statement. When used inside of a function, var defines variables with function-scope. The vars are not accessible from outside of the function. There is no other granularity of scope in JavaScript. In particular, there is no block-scope.Any variables used in a function which are not explicitly defined as var are assumed to belong to an outer scope, possibly to the Global Object.Vars which are not explicitly initialized are given the value undefined.Vars are not typed. A var can contain a reference to an object, or a string or a number or a boolean or null or undefined.A new set of vars is made every time the function is called. This allows functions to be recursive.

Closure

Functions can be defined inside of other functions. The inner function has access to the vars and parameters of the outer function. If a reference to an inner function survives (for example, as a callback function), the outer function’s vars also survive.

Return

JavaScript does not have a void type, so every function must return a value. The default value is undefined, except for constructors, where the default return value is this.

Statements

The set of named statements includes var, if, switch, for, while, do, break, continue, return, try, throw, and with. Most of them work the same as in other C-like languages.The var statement is a list of one or more variables names, separated by commas, with optional initialization expressions.

var a, b = window.document.body;

If the var statement appears outside of any function, it adds members to the Global Object. If it appears inside of a function, it defines local variables of the function.In if statements, while statements, do statements, and logical operators, JavaScript treats false, null, undefined, "" (the empty string), and the number 0 as false. All other values are treated as true.The case labels in a switch statement can be expressions. They don’t have to be constants. They can be strings.There are two forms of the for statement. The first is the common ( init; test; inc) form. The second is an object iterator.

for (name in object) {    if (object.hasOwnProperty(name)) {        value = object[name];    }}

The block is executed for each name in the object. The order in which the names are produced is not guaranteed.Statements can have a label prefix, which is an identifier followed with a colon.The with statement should not be used.

Operators

JavaScript has a fairly large set of operators. Most of them work the same way as in other C-like languages. There are a few differences to watch out for.The + operator is used for both addition and concatenation. If either of the operands is a string, it concatenates. This can cause errors. For example, '$' + 3 + 4 produces '$34', not '$7'.+ can be used as a prefix operator, converting its string operand to a number.!! can be used as a prefix operator, converting its operand to a boolean.The && operator is commonly called logical and. It can also be called guard. If the first operand is false, null, undefined, "" (the empty string), or the number 0 then it returns the first operand. Otherwise, it returns the second operand. This provides a convenient way to write a null-check:

var value = p && p.name; /* The name value willonly be retrieved from p if p has a value, avoiding an error. */

The || operator is commonly called logical or. It can also be called default. If the first operand is false, null, undefined, "" (the empty string), or the number 0, then it returns the second operand. Otherwise, it returns the first operand. This provides a convenient way to specify default values:

value = v || 10; /* Use the value of v, but if vdoesn't have a value, use 10 instead. */

JavaScript supplies a set of bitwise and shift operators, but does not have an Integer type to apply them to. What happens is the Number operand (a 64-bit floating-point number) is converted to a 32-bit integer before the operation, and then converted back to floating point after the operation.In JavaScript, void is a prefix operator, not a type. It always returns undefined. This has very little value. I only mention it in case you accidently type void out of habit and are puzzled by the strange behavior.The typeof operator returns a string based on the type of its operand.Mistakes were made.

Object 'object'
Array 'object'
Function 'function'
String 'string'
Number 'number'
Boolean 'boolean'
null 'object'
undefined 'undefined'

Potpourri

Global Object

The Global Object is the keeper of all of the functions and variables which were not defined inside of other functions and objects. Surprisingly, the Global Object does not have an explicit name in the language. Sometimes the this variable points at it, but often not. In the web browsers, window and self are members of the Global Object which point to the Global Object, thus giving an indirect way of addressing it.If a variable is accessed, but is not found in the current scope, it is looked for in the Global Object. If it is not found there, an error will result.The ECMAScript specification does not talk about the possibility of multiple Global Objects, or contexts, but browsers support this. Each window has its own Global Object.

Semicolon Insertion

One of the mistakes in the language is semicolon insertion. This is a technique for making semicolons optional as statement terminators. It is reasonable for IDEs and shell programs to do semicolon insertion. It is not reasonable for the language definition to require compilers to do it. Use semicolons.

Reserved Words

JavaScript is very heavy handed in its restrictions on reserved words. The reserved words are

abstractboolean break bytecase catch char class const continuedebugger default delete do doubleelse enum export extendsfalse final finally float for functiongotoif implements import in instanceof int interfacelongnative new nullpackage private protected publicreturnshort static super switch synchronizedthis throw throws transient true try typeofvar volatile voidwhile with

Most of those words are not even used in the language. A reserved word cannot be used

  1. As a name in literal object notation
  2. As a member name in dot notation
  3. As a function argument
  4. As a var
  5. As an unqualified global variable
  6. As a statement label

There is no excuse for the first two restrictions. None. There is an excuse for the second two restrictions, but it is very weak.

This is a set of coding conventions and rules for use in JavaScript programming. It is inspired by the Sun document Code Conventions for the Java Programming Language. It is heavily modified of course because JavaScript is not Java.The long-term value of software to an organization is in direct proportion to the quality of the codebase. Over its lifetime, a program will be handled by many pairs of hands and eyes. If a program is able to clearly communicate its structure and characteristics, it is less likely that it will break when modified in the never-too-distant future.Code conventions can help in reducing the brittleness of programs.All of our JavaScript code is sent directly to the public. It should always be of publication quality.Neatness counts.

JavaScript Files

JavaScript programs should be stored in and delivered as .js files.JavaScript code should not be embedded in HTML files unless the code is specific to a single session. Code in HTML adds significantly to pageweight with no opportunity for mitigation by caching and compression.<script src= filename.js> tags should be placed as late in the body as possible. This reduces the effects of delays imposed by script loading on other page components. There is no need to use the language or type attributes. It is the server, not the script tag, that determines the MIME type.

Indentation

The unit of indentation is four spaces. Use of tabs should be avoided because (as of this writing in the 21st Century) there still is not a standard for the placement of tabstops. The use of spaces can produce a larger filesize, but the size is not significant over local networks, and the difference is eliminated by minification.

Line Length

Avoid lines longer than 80 characters. When a statement will not fit on a single line, it may be necessary to break it. Place the break after an operator, ideally after a comma. A break after an operator decreases the likelihood that a copy-paste error will be masked by semicolon insertion. The next line should be indented 8 spaces.

Comments

Be generous with comments. It is useful to leave information that will be read at a later time by people (possibly yourself) who will need to understand what you have done. The comments should be well-written and clear, just like the code they are annotating. An occasional nugget of humor might be appreciated. Frustrations and resentments will not.It is important that comments be kept up-to-date. Erroneous comments can make programs even harder to read and understand.Make comments meaningful. Focus on what is not immediately visible. Don’t waste the reader’s time with stuff like

    i = 0; // Set i to zero.

Generally use line comments. Save block comments for formal documentation and for commenting out.

Variable Declarations

All variables should be declared before used. JavaScript does not require this, but doing so makes the program easier to read and makes it easier to detect undeclared variables that may become implied globals. Implied global variables should never be used.The var statements should be the first statements in the function body.It is preferred that each variable be given its own line and comment. They should be listed in alphabetical order.

    var currentEntry; // currently selected table entry
    var level;        // indentation level
    var size;         // size of table

JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.Use of global variables should be minimized. Implied global variables should never be used.

Function Declarations

All functions should be declared before they are used. Inner functions should follow the var statement. This helps make it clear what variables are included in its scope.There should be no space between the name of a function and the ( (left parenthesis) of its parameter list. There should be one space between the ) (right parenthesis) and the { (left curly brace) that begins the statement body. The body itself is indented four spaces. The } (right curly brace) is aligned with the line containing the beginning of the declaration of the function.

    function outer(c, d) {
        var e = c * d;
        function inner(a, b) {
            return (e * a) + b;
        }
        return inner(0, 1);
    }

This convention works well with JavaScript because in JavaScript, functions and object literals can be placed anywhere that an expression is allowed. It provides the best readability with inline functions and complex structures.

    function getElementsByClassName(className) {
        var results = [];
        walkTheDOM(document.body, function (node) {
            var a;        // array of class names
            var c = node.className; // the node's classname
            var i;                  // loop counter
            // If the node has a class name, then split it into a list of simple names.
            // If any of them match the requested name, then append the node to the set of results.
            if (c) {
                a = c.split(' ');
                for (i = 0; i < a.length; i += 1) {
                    if (a[i] === className) {
                        results.push(node);
                        break;
                    }
                }
            }
        });
        return results;
    }

If a function literal is anonymous, there should be one space between the word function and the ( (left parenthesis). If the space is omited, then it can appear that the function’s name is function, which is an incorrect reading.

    div.onclick = function (e) {
        return false;
    };
    that = {
        method: function () {
            return this.datum;
        },
        datum: 0
    };

Use of global functions should be minimized.When a function is to be invoked immediately, the entire invocation expression should be wrapped in parens so that it is clear that the value being produced is the result of the function and not the function itself.

var collection = (function () {
    var keys = [], values = [];
    return {
        get: function (key) {
            var at = keys.indexOf(key);
            if (at >= 0) {
                return value[at];
            }
        },
        set: function (key, value) {
            var at = keys.indexOf(key);
            if (at < 0) {
                at = keys.length;
            }
            keys[at] = key;
            value[at] = value;
        },
        remove: function (key) {
            var at = keys.indexOf(key);
            if (at >= 0) {
                keys.splice(at, 1);
                value.splice(at, 1);
            }
        }
    };
}());

Names

Names should be formed from the 26 upper and lower case letters (A .. Z, a .. z), the 10 digits (0 .. 9), and _ (underbar). Avoid use of international characters because they may not read well or be understood everywhere. Do not use $ (dollar sign) or \ (backslash) in names.Do not use _ (underbar) as the first character of a name. It is sometimes used to indicate privacy, but it does not actually provide privacy. If privacy is important, use the forms that provide private members. Avoid conventions that demonstrate a lack of competence.Most variables and functions should start with a lower case letter.Constructor functions which must be used with the new prefix should start with a capital letter. JavaScript issues neither a compile-time warning nor a run-time warning if a required new is omitted. Bad things can happen if new is not used, so the capitalization convention is the only defense we have.Global variables should be in all caps. (JavaScript does not have macros or constants, so there isn’t much point in using all caps to signify features that JavaScript doesn’t have.)

Statements

Simple Statements

Each line should contain at most one statement. Put a ; (semicolon) at the end of every simple statement. Note that an assignment statement which is assigning a function literal or object literal is still an assignment statement and must end with a semicolon.JavaScript allows any expression to be used as a statement. This can mask some errors, particularly in the presence of semicolon insertion. The only expressions that should be used as statements are assignments and invocations.

Compound Statements

Compound statements are statements that contain lists of statements enclosed in { } (curly braces).

  • The enclosed statements should be indented four more spaces.
  • The { (left curly brace) should be at the end of the line that begins the compound statement.
  • The } (right curly brace) should begin a line and be indented to align with the beginning of the line containing the matching { (left curly brace).
  • Braces should be used around all statements, even single statements, when they are part of a control structure, such as an if or for statement. This makes it easier to add statements without accidentally introducing bugs.

Labels

Statement labels are optional. Only these statements should be labeled: while, do, for, switch.

return Statement

A return statement with a value should not use ( ) (parentheses) around the value. The return value expression must start on the same line as the return keyword in order to avoid semicolon insertion.

if Statement

The if class of statements should have the following form: if ( condition) { statements}if ( condition) { statements} else { statements}if ( condition) { statements} else if ( condition) { statements} else { statements}

for Statement

A for class of statements should have the following form: for ( initialization; condition; update) { statements}for ( variable in object) {if ( filter) { statements}}The first form should be used with arrays and with loops of a predeterminable number of iterations.The second form should be used with objects. Be aware that members that are added to the prototype of the object will be included in the enumeration. It is wise to program defensively by using the hasOwnProperty method to distinguish the true members of the object : for ( variable in object) {if ( object.hasOwnProperty( variable)) { statements}}

while Statement

A while statement should have the following form: while ( condition) { statements}

do Statement

A do statement should have the following form: do { statements} while ( condition);Unlike the other compound statements, the do statement always ends with a ; (semicolon).

switch Statement

A switch statement should have the following form: switch ( expression) {case expression: statementsdefault: statements}Each case is aligned with the switch. This avoids over-indentation.Each group of statements (except the default) should end with break, return, or throw. Do not fall through.

try Statement

The try class of statements should have the following form:try {statements} catch ( variable) {statements}try {statements} catch ( variable) {statements } finally {statements}

continue Statement

Avoid use of the continue statement. It tends to obscure the control flow of the function.

with Statement

The with statement should not be used.

Whitespace

Blank lines improve readability by setting off sections of code that are logically related.Blank spaces should be used in the following circumstances:

  • A keyword followed by ( (left parenthesis) should be separated by a space.
        while (true) {
  • A blank space should not be used between a function value and its ( (left parenthesis). This helps to distinguish between keywords and function invocations.
  • All binary operators except . (period) and ( (left parenthesis) and [ (left bracket) should be separated from their operands by a space.
  • No space should separate a unary operator and its operand except when the operator is a word such as typeof.
  • Each ; (semicolon) in the control part of a for statement should be followed with a space.
  • Whitespace should follow every , (comma).

Bonus Suggestions

{} and []

Use {} instead of new Object(). Use [] instead of new Array().Use arrays when the member names would be sequential integers. Use objects when the member names are arbitrary strings or names.

, (comma) Operator

Avoid the use of the comma operator except for very disciplined use in the control part of for statements. (This does not apply to the comma separator, which is used in object literals, array literals, var statements, and parameter lists.)

Block Scope

In JavaScript blocks do not have scope. Only functions have scope. Do not use blocks except as required by the compound statements.

Assignment Expressions

Avoid doing assignments in the condition part of if and while statements.Is

    if (a = b) {

a correct statement? Or was

    if (a == b) {

intended? Avoid constructs that cannot easily be determined to be correct.

=== and !== Operators.

It is almost always better to use the === and !== operators. The == and != operators do type coercion. In particular, do not use == to compare against falsy values.

Confusing Pluses and Minuses

Be careful to not follow a + with + or ++. This pattern can be confusing. Insert parens between them to make your intention clear.

    total = subtotal + +myInput.value;

is better written as

    total = subtotal + (+myInput.value);

so that the + + is not misread as ++.

eval is Evil

The eval function is the most misused feature of JavaScript. Avoid it.eval has aliases. Do not use the Function constructor. Do not pass strings to setTimeout or setInterval.

Powered by WordPress | Theme: by 85ideas. Editor by Khoanguyen