JavaScript: The Good Parts

Chapter 1 Good Parts:

JavaScript is an important language because it is the language of the web browser.

The very good ideas include functions, loose typing, dynamic objects, and an expressive object literal notation. The bad ideas include a programming model based on global variables.

The Web has become an important platform for application development, and JavaScript is the only language that is found in all browsers.

 

Chapter 2 Grammar:

Javascript中的保留字,但是大部分却没在这个语言中使用。undefined,NaN,Infinity也应该算保留字。

abstract 
boolean break byte 
case catch char class const continue 
debugger default delete do double
else enum export extends 
false final finally float for function 
goto 
if implements import in instanceof int interface 
long 
native new null 
package private protected public 
return 
short static super switch synchronized 
this throw throws transient true try typeof 
var volatile void 
while with
Reserved Words

JavaScript has a single number type. Internally, it is represented as 64-bit floating point, the same as Java's double. 1 and 1.0 are the same value.

NaN is not equal to any value, including itself. You can detect NaN with the isNaN(number) function. JavaScript has a Math object that contains a set of methods that act on numbers. Math.floor(number) method can be used to convert a number into an integer.

All characters in JavaScript are 16 bits wide. "A" === "\u0041". Strings are immutable.

A block is a set of statements wrapped in curly braces. Unlike many other languages, blocks in JavaScript do not create a new scope, so variables should be defined at the top of the function, not in blocks.

Below are the falsy values:

false
null
undefined
The empty string ''
The number 0
The number NaN
Falsy values

for in loop enumerates the property names (or keys) of an object. When iterating an array, use for (i = 0; i < arr.length; i++) { }. It is usually necessary to test object.hasOwnProperty(variable) to determine whether the property name is truly a member of the object or was found instead on the prototype chain.

var arr = [1,2,3,4,5,6,7,8,9];
arr[12] = 34;
for (var i in arr) {
    console.log(i + " - " + arr[i]);  
}

for (var i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}
For loop

The try statement executes a block and catches any exceptions that were thrown by the block. The catch clause defines a new variable that will receive the exception object.

The throw statement raises an exception. If the throw statement is in a try block, then control goes to the catch clause. Otherwise, the function invocation is abandoned, and control goes to the catch clause of the try in the calling function.

JavaScript does not allow a line end between the return and the expression.

 

Chapter 3 Objects:

The simple types of JavaScript are numbers, strings, booleans (true and false), null, and undefined. All other values are objects. In JavaScript, arrays, functions, regular expressions, and objects are 'objects'.

The || operator can be used to fill in default values:

var middle = stooge["middle-name"] || "none";
var status = flight.status || "unknown";
|| operator

Attempting to retrieve values from undefined will throw a TypeError exception. This can be guarded against with the && operator:

flight.equipment                                         // undefined
flight.equipment.model                               // throw "TypeError"
flight.equipment && flight.equipment.model // undefined
&& operator

Objects are passed around by reference. They are never copied.

All objects created from object literals are linked to Object.prototype, an object that comes standard with JavaScript.

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

var another_stooge = Object.create(stooge);
Prototype

If we add a new property to a prototype, that property will immediately be visible in all of the objects that are based on that prototype.

The hasOwnProperty method does not look at the prototype chain.

Global abatement => Use a global object to create a top-level structure or use closure for information hiding.

 

Chapter 4 Functions:

 - The method invocation pattern

var myObject = {
    value: 0,
    increment: function  (inc) {
        this.value += typeof inc === 'number' ? inc : 1;
    }
};

myObject.increment(1);
document.writeln(myObject.value);  //1

myObject.increment(2);
document.writeln(myObject.value);  // 3
Example

 - The function invocation pattern

When a function is not the property of an object, then it is invoked as a function, this is bound to the global object.

var me = {name: "Dave", 
    value: 4,
    getName: function() { return this.name; }
};

var add = function(a, b) { return a + b; };
me.double = function () {
    var helper = function () {
        console.log(this);
    };
    helper();
};
me.double();
console.log(me.value);
This is bound to global object
var me = {name: "Shuai", 
    value: 4,
    getName: function() { return this.name; }
};

var add = function(a, b) { return a + b; };
me.double = function () {
    var that = this;
    var helper = function () {
        that.value = add(that.value, that.value);
    };
    helper();
};
me.double();
console.log(me.value);
Use that to represent this

 - The constructor invocation pattern

var Quo = function (string) {     
    this.status = string; 
}; // Give all instances of Quo a public method Invocation 
Quo.prototype.get_status = function () {     
    return this.status; 
}; 
// Make an instance of Quo. 
var myQuo = new Quo("confused"); 
console.log(myQuo.get_status( ));  // confused

for (var prop in myQuo) {
    if (myQuo.hasOwnProperty(prop)) {
        console.log(prop);
    }
}
Example

 - The apply invocation pattern

var add = function (a, b) {
    return a + b;
};

var arr = [3,4,5];
var sum = add.apply(null, arr);
console.log(sum);

var statusObject = { status: "A-OK"};

var Quo = function (string) {     
    this.status = string; 
}; // Give all instances of Quo a public method Invocation 
Quo.prototype.get_status = function () {     
    return this.status; 
}; 
// statusObject does not inherit from Quo.prototype, 
// but we can invoke the get_status method on 
// statusObject even though statusObject does not have 
// a get_status method.
var getStatus = Quo.prototype.get_status.apply(statusObject);
console.log(getStatus);
Apply

A function always returns a value.If the return value is not specified,then undefined is returned

var add = function (a, b) {     
    if (typeof a !== 'number' || typeof b !== 'number') {         
        throw {             
            name: 'TypeError',             
            message: 'add needs numbers'         
        };     
    }     
    return a + b; 
}

try {
    add("seven");
} catch (e) {
    console.log(e.name + ": " + e.message);
}
Example of Try...Catch...

By augmenting Function.prototype, we can make a method available to all functions:

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

Number.method("integer", function() {
    return Math[this < 0 ? "ceil" : "floor"](this);
});

console.log((-10 / 3).integer());

String.method('trim', function () {     
    return this.replace(/^\s+|\s+$/g, ''); 
});
console.log("    neat     ".trim());
Augment

Notice the () on the last line. The function returns an object containing two methods, and those methods continue to enjoy the privilege of access to the value variable.

var myObject = (function () {
    var value = 0;
    
    return {
        increment: function (inc) {
            value += typeof inc === 'number' ? inc : 1;
        },
        getValue: function () {
            return value;
        }
    };
}()); 
private members
var quo = function (status) {
    return {
        get_status: function () {
            return status;
        }
    };
};

var myQuo = quo("amazed");
console.log(myQuo.get_status());
Use function to define an object

The function has access to the context in which it was created. This is called closure.

var fade = function (node) {
    var level = 1;
    var step = function () {
        var hex = level.toString(16);
        node.style.backgroundColor = '#FFFF' + hex + hex;
        if (level < 15) {
            level += 1;
            setTimeout(step, 100);
        }
    };     
    setTimeout(step, 100);
};

fade(document.body);



<html>
    <body>
        <pre>
            <script src="program.js"></script>
        </pre>
    </body>
</html>
Fade the html page

Avoid creating functions within a loop. It can be wasteful computationally, and it can cause confusion, as we saw with the bad example.

// BAD EXAMPLE 
// Make a function that assigns event handler functions to an array of nodes the wrong way. 
// When you click on a node, an alert box is supposed to display the ordinal of the node. 
// But it always displays the number of nodes instead. 
var add_the_handlers = function (nodes) {     
    var i;     
    for (i = 0; i < nodes.length; i += 1) {         
        nodes[i].onclick = function (e) {             
            alert(i);         
        };     
    } 
};

// BETTER EXAMPLE 
// Make a function that assigns event handler functions to an array of nodes. 
// When you click on a node, an alert box will display the ordinal of the node. var add_the_handlers = function (nodes) {     
    var helper = function (i) {         
        return function (e) {             
            alert(i);         
        };     
    };     
    var i;     
    for (i = 0; i < nodes.length; i += 1) {         
        nodes[i].onclick = helper(i);     
    } 
};
Function context
String.method('deentityify', function () { 
    // The entity table. It maps entity names to 
    // characters.    
    var entity = {         
        quot: '"',
        lt:   '<',         
        gt:   '>'     
    }; 
    // Return the deentityify method.     
    return function ( ) { 
        // This is the deentityify method. It calls the string 
        // replace method, looking for substrings that start 
        // with '&' and end with ';'. If the characters in 
        // between are in the entity table, then replace the 
        // entity with the character from the table. It uses 
        // a regular expression (Chapter 7).         
        return this.replace(/&([^&;]+);/g,             
            function (a, b) {                 
                var r = entity[b];                 
                return typeof r === 'string' ? r : a;             
            }        
        );     
    }; 
}());
console.log('&lt;&quot;&gt;'.deentityify( ));  // <">
Create a Module
var serial_maker = function ( ) { 
    // Produce an object that produces unique strings. A 
    // unique string is made up of two parts: a prefix 
    // and a sequence number. The object comes with 
    // methods for setting the prefix and sequence 
    // number, and a gensym method that produces unique 
    // strings.     
    var prefix = '';     
    var seq = 0;     
    return {         
        set_prefix: function (p) {             
            prefix = String(p);         
        },         
        set_seq: function (s) {             
            seq = s;         
        },         
        gensym: function ( ) {             
            var result = prefix + seq;             
            seq += 1;             
            return result;         
        }     
    }; 
}; 
var seqer = serial_maker( ); 
seqer.set_prefix('Q'); 
seqer.set_seq(1000); 
var unique = seqer.gensym( );    // unique is "Q1000"
Use module to write secure code
var memoizer = function (memo, formula) {     
    var recur = function (n) {         
        var result = memo[n];         
        if (typeof result !== 'number') {             
            result = formula(recur, n);             
            memo[n] = result;         
        }         
        return result;     
    };     
    return recur; 
};

var fibonacci = memoizer([0, 1], function (recur, n) {     
    return recur(n - 1) + recur(n - 2); 
});

var factorial = memoizer([1, 1], function (recur, n) {     
    return n * recur(n - 1); 
});

console.log(fibonacci(5));
console.log(factorial(5));
Memoization

 

Chaper 5 Inheritance:

JavaScript is a prototypal language,which means that objects inherit directly from other objects.

 

Chapter 6 Arrays:

Instead, JavaScript provides an object that has some array-like characteristics. It converts array subscripts into strings that are used to make properties. It is significantly slower than a real array, but it can be more convenient to use. Retrieval and updating of properties work the same as with objects, except that there is a special trick with integer property names. Arrays have their own literal format.

numbers.push('go');   // numbers is ['zero', 'one', 'two', 'shi', 'go']
delete numbers[2];    // numbers is ['zero', 'one', undefined, 'shi', 'go']
numbers.splice(2, 1); // numbers is ['zero', 'one', 'shi', 'go'], not go quickly for large arrays
Operations on Array

Distinguish between arrays and objects

var is_array = function (value) {     
    return value && typeof value === 'object' && value.constructor === Array; 
};

Unfortunately,it fails to identify arrays that were constructed in a different window or frame.If we want to accurately detect those foreign arrays,we have to work a little harder:

var is_array2 = function (value) {     
    return Object.prototype.toString.apply(value) === '[object Array]';  
};

var arr = ["Red", true];
console.log(is_array(arr));
console.log(is_array2(arr));
Determine whether it is an array

 

Chapter 7 Regular Expressions:

var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/; var url = "http://www.ora.com:80/goodparts?q#fragment";

var result = parse_url.exec(url); 
var names = ['url', 'scheme', 'slash', 'host', 'port', 'path', 'query', 'hash']; 
var blanks = '      '; 

var i; 
for (i = 0; i < names.length; i += 1) {     
    console.log(names[i] + ':' + blanks.substring(names[i].length), result[i]); 
}
An example

 

Chapter 8 Methods:

array.concat(item...)
array.join(separator) //faster than using '+'
array.pop()
array.push(item...)
array.reverse()
array.shift()
array.slice(start, end)
array.sort(comparefn)
array.splice()
array.unshift(item...)

number.toExponential(fractionDigits)
number.toFixed(fractionDigits)
number.toPrecision(precision)
number.toString(radix)

object.hasOwnProperty(name)

regexp.exec(string)
regexp.test(string)

string.charAt(pos)
stirng.charCodeAt(pos)
string.concat(string...)
stirng.indexOf(searchString, position)
string.lastIndexOf(searchString, position)
string.localeCompare(that)
string.match(regexp)
string.replace(searchValue, replaceValue)
string.search(regexp)
string.slice(start, end)
string.split(separator, limit)
string.substring(start, end)
string.toLocaleLowerCase()
string.toLocaleUpperCase()
string.toLowerCase()
string.toUpperCase()
String.fromCharCode(char...)
View Code

Chapter 9 Style

Chapeter 10 Beautiful Features

 

APPENDIX

Awful Parts:

Global variables

Scope

A variable declared in a block is visible everywhere in the function containing the block.

Semicolon Insertion

...

Bad Parts

JSLint

Syntax Diagrams

JSON

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值