├── README.md ├── appa.txt ├── appb.txt ├── appc.txt ├── appe.txt ├── 第1章 精华 └── 简单示例.md ├── 第2章 语法 ├── 函数.md ├── 字符串.md ├── 字面量.md ├── 数字.md ├── 标识符.md ├── 空白.md ├── 表达式.md └── 语句.md ├── 第3章 对象 ├── 减少全局变量污染.md ├── 删除.md ├── 原型.md ├── 反射.md ├── 对象字面量.md ├── 引用.md ├── 更新.md ├── 枚举.md └── 检索.md ├── 第4章 函数 ├── 作用域.md ├── 函数字面量.md ├── 函数对象.md ├── 参数.md ├── 回调.md ├── 异常.md ├── 扩充类型的功能.md ├── 柯里化.md ├── 模块.md ├── 级联.md ├── 记忆.md ├── 调用.md ├── 返回.md ├── 递归.md └── 闭包.md ├── 第5章 继承 ├── 伪类.md ├── 函数化.md ├── 原型.md ├── 对象说明符.md └── 部件.md ├── 第6章 数组 ├── 删除.md ├── 容易混淆的地方.md ├── 指定初始值.md ├── 数组字面量.md ├── 方法.md ├── 枚举.md └── 长度.md ├── 第7章 正则表达式 ├── 一个例子.md ├── 元素.md └── 结构.md ├── 第8章 方法 ├── Array.md ├── Function.md ├── Number.md ├── Object.md ├── RegExp.md └── String.md └── 第9章 代码风格 └── ch09.md /README.md: -------------------------------------------------------------------------------- 1 | # JavaScript-The-Good-Parts-Source-Code 2 | JavaScript语言精粹 源代码 3 | -------------------------------------------------------------------------------- /appa.txt: -------------------------------------------------------------------------------- 1 | appendix: Awful Parts 2 | ================== 3 | var foo = value; 4 | 5 | 6 | ==================================== 7 | window.foo = value; 8 | 9 | 10 | ==================================== 11 | foo = value; 12 | 13 | 14 | ==================================== 15 | return 16 | { 17 | status: true 18 | }; 19 | 20 | 21 | ==================================== 22 | return { 23 | status: true 24 | }; 25 | 26 | 27 | ==================================== 28 | abstract boolean break byte case catch char class const continue 29 | debugger default delete do double else enum export extends false final 30 | finally float for 31 | function goto if implements import in instanceof int interface long native new null 32 | package private protected public return short static super switch synchronized this 33 | throw throws transient true try typeof var volatile void while with 34 | 35 | 36 | ==================================== 37 | var method; // ok 38 | var class; // illegal 39 | object = {box: value}; // ok 40 | object = {case: value}; // illegal 41 | object = {'case': value}; // ok 42 | object.box = value; // ok 43 | object.case = value; // illegal 44 | object['case'] = value; // ok 45 | 46 | 47 | ==================================== 48 | typeof 98.6 49 | 50 | 51 | ==================================== 52 | typeof null 53 | 54 | 55 | ==================================== 56 | my_value === null 57 | 58 | 59 | ==================================== 60 | if (my_value && typeof my_value === 'object') { 61 | // my_value is an object or an array! 62 | } 63 | 64 | 65 | ==================================== 66 | typeof /a/ 67 | 68 | 69 | ==================================== 70 | typeof NaN === 'number' // true 71 | 72 | 73 | ==================================== 74 | + '0' // 0 75 | + 'oops' // NaN 76 | 77 | 78 | ==================================== 79 | NaN === NaN // false 80 | NaN !== NaN // true 81 | 82 | 83 | ==================================== 84 | isNaN(NaN) // true 85 | isNaN(0) // false 86 | isNaN('oops') // true 87 | isNaN('0') // false 88 | 89 | 90 | ==================================== 91 | var isNumber = function isNumber(value) { 92 | return typeof value === 'number' && isFinite(value); 93 | }; 94 | 95 | 96 | ==================================== 97 | if (Object.prototype.toString.apply(my_value) === '[object Array]'){ 98 | // my_value is truly an array! 99 | } 100 | 101 | 102 | ==================================== 103 | if (my_value && typeof my_value === 'object' && 104 | typeof my_value.length === 'number' && 105 | !(my_value.propertyIsEnumerable('length')) { 106 | // my_value is truly an array! 107 | } 108 | 109 | 110 | ==================================== 111 | value = myObject[name]; 112 | if (value == null) { 113 | alert(name + ' not found.'); 114 | } 115 | 116 | 117 | ==================================== 118 | var name; 119 | another_stooge.hasOwnProperty = null; // trouble 120 | for (name in another_stooge) { 121 | if (another_stooge.hasOwnProperty(name)) { // boom 122 | document.writeln(name + ': ' + another_stooge[name]); 123 | } 124 | } 125 | 126 | 127 | ==================================== 128 | var i; 129 | var word; 130 | var text = 131 | "This oracle of comfort has so pleased me, " + 132 | "That when I am in heaven I shall desire " + 133 | "To see what this child does, " + 134 | "and praise my Constructor."; 135 | 136 | var words = text.toLowerCase( ).split(/[\s,.]+/); 137 | var count = {}; 138 | for (i = 0; i < words.length; i += 1) { 139 | word = words[i]; 140 | if (count[word]) { 141 | count[word] += 1; 142 | } else { 143 | count[word] = 1; 144 | } 145 | } 146 | 147 | 148 | ==================================== 149 | if (typeof count[word] === 'number') { 150 | 151 | 152 | ================== -------------------------------------------------------------------------------- /appb.txt: -------------------------------------------------------------------------------- 1 | appendix: Bad Parts 2 | ================== 3 | '' == '0' // false 4 | 0 == '' // true 5 | 0 == '0' // true 6 | 7 | false == 'false' // false 8 | false == '0' // true 9 | 10 | false == undefined // false 11 | false == null // false 12 | null == undefined // true 13 | 14 | ' \t\r\n ' == 0 // true 15 | 16 | 17 | ==================================== 18 | with (obj) { 19 | a = b; 20 | } 21 | 22 | 23 | ==================================== 24 | if (obj.a === undefined) { 25 | a = obj.b === undefined ? b : obj.b; 26 | } else { 27 | obj.a = obj.b === undefined ? b : obj.b; 28 | } 29 | 30 | 31 | ==================================== 32 | a = b; 33 | a = obj.b; 34 | obj.a = b; 35 | obj.a = obj.b; 36 | 37 | 38 | ==================================== 39 | eval("myValue = myObject." + myKey + ";"); 40 | 41 | 42 | ==================================== 43 | myvalue = myObject[myKey]; 44 | 45 | 46 | ==================================== 47 | if (ok) 48 | t = true; 49 | 50 | 51 | ==================================== 52 | if (ok) 53 | t = true; 54 | advance( ); 55 | 56 | 57 | ==================================== 58 | if (ok) { 59 | t = true; 60 | advance( ); 61 | } 62 | 63 | 64 | ==================================== 65 | if (ok) { 66 | t = true; 67 | } 68 | advance( ); 69 | 70 | 71 | ==================================== 72 | for (p = src, q = dest; !*p; p++, q++) *q = *p; 73 | 74 | 75 | ==================================== 76 | & and 77 | | or 78 | ^ xor 79 | ˜ not 80 | >> signed right shift 81 | >>> unsigned right shift 82 | << left shift 83 | 84 | 85 | ==================================== 86 | function foo( ) {} 87 | 88 | 89 | ==================================== 90 | var foo = function foo( ) {}; 91 | 92 | 93 | ==================================== 94 | (function ( ) { 95 | var hidden_variable; 96 | 97 | // This function can have some impact on 98 | // the environment, but introduces no new 99 | // global variables. 100 | }()); 101 | 102 | 103 | ==================================== 104 | new Boolean(false) 105 | 106 | 107 | ================== -------------------------------------------------------------------------------- /appc.txt: -------------------------------------------------------------------------------- 1 | appendix: JSLint 2 | ================== 3 | /*global getElementByAttribute, breakCycles, hanoi */ 4 | 5 | 6 | ==================================== 7 | /*members doTell, iDoDeclare, mercySakes, 8 | myGoodness, ohGoOn, wellShutMyMouth */ 9 | 10 | 11 | ==================================== 12 | /*jslint nomen: true, evil: false */ 13 | 14 | 15 | ==================================== 16 | , ; : { } ( [ = < > ? ! + - * / % ˜ ^ | & 17 | == != <= >= += -= *= /= %= ^= |= &= << >> || && 18 | === !== <<= >>= >>> >>>= 19 | 20 | 21 | ==================================== 22 | ) ] . ++ -- 23 | 24 | 25 | ==================================== 26 | if (condition) 27 | statement; 28 | 29 | 30 | ==================================== 31 | if (condition) { 32 | statements; 33 | } 34 | 35 | 36 | ==================================== 37 | for (name in object) { 38 | if (object.hasOwnProperty(name)) { 39 | .... 40 | } 41 | } 42 | 43 | 44 | ==================================== 45 | if (a = b) { 46 | ... 47 | } 48 | 49 | 50 | ==================================== 51 | if (a == b) { 52 | ... 53 | } 54 | 55 | 56 | ==================================== 57 | 0 '' undefined null false true 58 | 59 | 60 | ==================================== 61 | (foo != 0) 62 | 63 | 64 | ==================================== 65 | (foo) 66 | 67 | 68 | ==================================== 69 | (foo == 0) 70 | 71 | 72 | ==================================== 73 | (!foo) 74 | 75 | 76 | ================== -------------------------------------------------------------------------------- /appe.txt: -------------------------------------------------------------------------------- 1 | appendix: JSON 2 | ================== 3 | [ 4 | { 5 | "first": "Jerome", 6 | "middle": "Lester", 7 | "last": "Howard", 8 | "nick-name": "Curly", 9 | "born": 1903, 10 | "died": 1952, 11 | "quote": "nyuk-nyuk-nyuk!" 12 | }, 13 | { 14 | "first": "Harry", 15 | "middle": "Moses", 16 | "last": "Howard", 17 | "nick-name": "Moe", 18 | "born": 1897, 19 | "died": 1975, 20 | "quote": "Why, you!" 21 | }, 22 | { 23 | "first": "Louis", 24 | "last": "Feinberg", 25 | "nick-name": "Larry", 26 | "born": 1902, 27 | "died": 1975, 28 | "quote": "I'm sorry. Moe, it was an accident!" 29 | } 30 | ] 31 | 32 | 33 | ==================================== 34 | var myData = eval('(' + myJSONText + ')'); 35 | 36 | 37 | ==================================== 38 | var json_parse = function () { 39 | 40 | // This is a function that can parse a JSON text, producing a JavaScript 41 | // data structure. It is a simple, recursive descent parser. 42 | 43 | // We are defining the function inside of another function to avoid creating 44 | // global variables. 45 | 46 | var at, // The index of the current character 47 | ch, // The current character 48 | escapee = { 49 | '"': '"', 50 | '\\': '\\', 51 | '/': '/', 52 | b: 'b', 53 | f: '\f', 54 | n: '\n', 55 | r: '\r', 56 | t: '\t' 57 | }, 58 | text, 59 | 60 | error = function (m) { 61 | 62 | // Call error when something is wrong. 63 | 64 | throw { 65 | name: 'SyntaxError', 66 | message: m, 67 | at: at, 68 | text: text 69 | }; 70 | }, 71 | 72 | next = function (c) { 73 | 74 | // If a c parameter is provided, verify that it matches the current character. 75 | 76 | if (c && c !== ch) { 77 | error("Expected '" + c + "' instead of '" + ch + "'"); 78 | } 79 | 80 | // Get the next character. When there are no more characters, 81 | // return the empty string. 82 | 83 | ch = text.charAt(at); 84 | at += 1; 85 | return ch; 86 | }, 87 | 88 | number = function () { 89 | 90 | // Parse a number value. 91 | 92 | var number, 93 | string = ''; 94 | 95 | if (ch === '-') { 96 | string = '-'; 97 | next('-'); 98 | } 99 | while (ch >= '0' && ch <= '9') { 100 | string += ch; 101 | next(); 102 | } 103 | if (ch === '.') { 104 | string += '.'; 105 | while (next() && ch >= '0' && ch <= '9') { 106 | string += ch; 107 | } 108 | } 109 | if (ch === 'e' || ch === 'E') { 110 | string += ch; 111 | next(); 112 | if (ch === '-' || ch === '+') { 113 | string += ch; 114 | next(); 115 | } 116 | while (ch >= '0' && ch <= '9') { 117 | string += ch; 118 | next(); 119 | } 120 | } 121 | number = +string; 122 | if (isNaN(number)) { 123 | error("Bad number"); 124 | } else { 125 | return number; 126 | } 127 | }, 128 | 129 | string = function () { 130 | 131 | // Parse a string value. 132 | 133 | var hex, 134 | i, 135 | string = '', 136 | uffff; 137 | 138 | // When parsing for string values, we must look for " and \ characters. 139 | 140 | if (ch === '"') { 141 | while (next()) { 142 | if (ch === '"') { 143 | next(); 144 | return string; 145 | } else if (ch === '\\') { 146 | next(); 147 | if (ch === 'u') { 148 | uffff = 0; 149 | for (i = 0; i < 4; i += 1) { 150 | hex = parseInt(next(), 16); 151 | if (!isFinite(hex)) { 152 | break; 153 | } 154 | uffff = uffff * 16 + hex; 155 | } 156 | string += String.fromCharCode(uffff); 157 | } else if (typeof escapee[ch] === 'string') { 158 | string += escapee[ch]; 159 | } else { 160 | break; 161 | } 162 | } else { 163 | string += ch; 164 | } 165 | } 166 | } 167 | error("Bad string"); 168 | }, 169 | 170 | white = function () { 171 | 172 | // Skip whitespace. 173 | 174 | while (ch && ch <= ' ') { 175 | next(); 176 | } 177 | }, 178 | 179 | word = function () { 180 | 181 | // true, false, or null. 182 | 183 | switch (ch) { 184 | case 't': 185 | next('t'); 186 | next('r'); 187 | next('u'); 188 | next('e'); 189 | return true; 190 | case 'f': 191 | next('f'); 192 | next('a'); 193 | next('l'); 194 | next('s'); 195 | next('e'); 196 | return false; 197 | case 'n': 198 | next('n'); 199 | next('u'); 200 | next('l'); 201 | next('l'); 202 | return null; 203 | } 204 | error("Unexpected '" + ch + "'"); 205 | }, 206 | 207 | value, // Place holder for the value function. 208 | 209 | array = function () { 210 | 211 | // Parse an array value. 212 | 213 | var array = []; 214 | 215 | if (ch === '[') { 216 | next('['); 217 | white(); 218 | if (ch === ']') { 219 | next(']'); 220 | return array; // empty array 221 | } 222 | while (ch) { 223 | array.push(value()); 224 | white(); 225 | if (ch === ']') { 226 | next(']'); 227 | return array; 228 | } 229 | next(','); 230 | white(); 231 | } 232 | } 233 | error("Bad array"); 234 | }, 235 | 236 | object = function () { 237 | 238 | // Parse an object value. 239 | 240 | var key, 241 | object = {}; 242 | 243 | if (ch === '{') { 244 | next('{'); 245 | white(); 246 | if (ch === '}') { 247 | next('}'); 248 | return object; // empty object 249 | } 250 | while (ch) { 251 | key = string(); 252 | white(); 253 | next(':'); 254 | object[key] = value(); 255 | white(); 256 | if (ch === '}') { 257 | next('}'); 258 | return object; 259 | } 260 | next(','); 261 | white(); 262 | } 263 | } 264 | error("Bad object"); 265 | }; 266 | 267 | value = function () { 268 | 269 | // Parse a JSON value. It could be an object, an array, a string, a number, 270 | // or a word. 271 | 272 | white(); 273 | switch (ch) { 274 | case '{': 275 | return object(); 276 | case '[': 277 | return array(); 278 | case '"': 279 | return string(); 280 | case '-': 281 | return number(); 282 | default: 283 | return ch >= '0' && ch <= '9' ? number() : word(); 284 | } 285 | }; 286 | 287 | // Return the json_parse function. It will have access to all of the above 288 | // functions and variables. 289 | 290 | return function (source, reviver) { 291 | var result; 292 | 293 | text = source; 294 | at = 0; 295 | ch = ' '; 296 | result = value(); 297 | white(); 298 | if (ch) { 299 | error("Syntax error"); 300 | } 301 | 302 | // If there is a reviver function, we recursively walk the new structure, 303 | // passing each name/value pair to the reviver function for possible 304 | // transformation, starting with a temporary boot object that holds the result 305 | // in an empty key. If there is not a reviver function, we simply return the 306 | // result. 307 | 308 | return typeof reviver === 'function' ? 309 | function walk(holder, key) { 310 | var k, v, value = holder[key]; 311 | if (value && typeof value === 'object') { 312 | for (k in value) { 313 | if (Object.hasOwnProperty.call(value, k)) { 314 | v = walk(value, k); 315 | if (v !== undefined) { 316 | value[k] = v; 317 | } else { 318 | delete value[k]; 319 | } 320 | } 321 | } 322 | } 323 | return reviver.call(holder, key, value); 324 | }({'': result}, '') : result; 325 | 326 | }; 327 | }(); 328 | 329 | 330 | ================== -------------------------------------------------------------------------------- /第1章 精华/简单示例.md: -------------------------------------------------------------------------------- 1 | chapter: Good Parts 2 |
4 | 5 | ```javascript 6 | document.writeln('Hello, world!'); 7 | 8 | Function.prototype.method = function (name, func) { 9 | this.prototype[name] = func; 10 | return this; 11 | }; 12 | 13 | ``` -------------------------------------------------------------------------------- /第2章 语法/函数.md: -------------------------------------------------------------------------------- 1 | chapter: Grammar 2 | ================== 3 | -------------------------------------------------------------------------------- /第2章 语法/字符串.md: -------------------------------------------------------------------------------- 1 | chapter: Grammar 2 | ================== 3 | ```javascript 4 | "A" === "\u0041" 5 | 6 | 7 | ==================================== 8 | 'c' + 'a' + 't' === 'cat' 9 | 10 | 11 | ==================================== 12 | 'cat'.toUpperCase( ) === 'CAT' 13 | ``` -------------------------------------------------------------------------------- /第2章 语法/字面量.md: -------------------------------------------------------------------------------- 1 | chapter: Grammar 2 | ================== 3 | -------------------------------------------------------------------------------- /第2章 语法/数字.md: -------------------------------------------------------------------------------- 1 | chapter: Grammar 2 | -------------------------------------------------------------------------------- /第2章 语法/标识符.md: -------------------------------------------------------------------------------- 1 | chapter: Grammar 2 | ================== 3 | ```javascript 4 | abstract 5 | boolean break byte 6 | case catch char class const continue 7 | debugger default delete do double 8 | else enum export extends 9 | false final finally float for function 10 | goto 11 | if implements import in instanceof int interface 12 | long 13 | native new null 14 | package private protected public 15 | return 16 | short static super switch synchronized 17 | this throw throws transient true try typeof 18 | var volatile void 19 | while with 20 | ``` 21 | -------------------------------------------------------------------------------- /第2章 语法/空白.md: -------------------------------------------------------------------------------- 1 | chapter: Grammar 2 | ================== 3 | ```javascript 4 | var that = this; 5 | 6 | 7 | ==================================== 8 | /* 9 | var rm_a = /a*/.match(s); 10 | */ 11 | ``` -------------------------------------------------------------------------------- /第2章 语法/表达式.md: -------------------------------------------------------------------------------- 1 | chapter: Grammar 2 | ================== 3 | ```javascript 4 | 2 + 3 * 5 === 17 5 | (2 + 3) * 5 === 25 6 | 7 | ``` 8 | ================== -------------------------------------------------------------------------------- /第2章 语法/语句.md: -------------------------------------------------------------------------------- 1 | chapter: Grammar 2 | ================== 3 | ```javascript 4 | for (myvar in obj) { 5 | if (obj.hasOwnProperty(myvar)) { 6 | ... 7 | } 8 | } 9 | ``` -------------------------------------------------------------------------------- /第3章 对象/减少全局变量污染.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | ```javascript 4 | var empty_object = {}; 5 | 6 | var stooge = { 7 | "first-name": "Jerome", 8 | "last-name": "Howard" 9 | }; 10 | 11 | 12 | ==================================== 13 | var flight = { 14 | airline: "Oceanic", 15 | number: 815, 16 | departure: { 17 | IATA: "SYD", 18 | time: "2004-09-22 14:55", 19 | city: "Sydney" 20 | }, 21 | arrival: { 22 | IATA: "LAX", 23 | time: "2004-09-23 10:42", 24 | city: "Los Angeles" 25 | } 26 | }; 27 | 28 | 29 | 30 | 31 | ==================================== 32 | var MYAPP = {}; 33 | 34 | 35 | ==================================== 36 | MYAPP.stooge = { 37 | "first-name": "Joe", 38 | "last-name": "Howard" 39 | }; 40 | 41 | MYAPP.flight = { 42 | airline: "Oceanic", 43 | number: 815, 44 | departure: { 45 | IATA: "SYD", 46 | time: "2004-09-22 14:55", 47 | city: "Sydney" 48 | }, 49 | arrival: { 50 | IATA: "LAX", 51 | time: "2004-09-23 10:42", 52 | city: "Los Angeles" 53 | } 54 | }; 55 | 56 | ``` -------------------------------------------------------------------------------- /第3章 对象/删除.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | ```javascript 4 | var empty_object = {}; 5 | 6 | var stooge = { 7 | "first-name": "Jerome", 8 | "last-name": "Howard" 9 | }; 10 | 11 | 12 | ==================================== 13 | var flight = { 14 | airline: "Oceanic", 15 | number: 815, 16 | departure: { 17 | IATA: "SYD", 18 | time: "2004-09-22 14:55", 19 | city: "Sydney" 20 | }, 21 | arrival: { 22 | IATA: "LAX", 23 | time: "2004-09-23 10:42", 24 | city: "Los Angeles" 25 | } 26 | }; 27 | 28 | 29 | 30 | another_stooge.nickname // 'Moe' 31 | 32 | // Remove nickname from another_stooge, revealing 33 | // the nickname of the prototype. 34 | 35 | delete another_stooge.nickname; 36 | 37 | another_stooge.nickname // 'Curly' 38 | 39 | ``` 40 | -------------------------------------------------------------------------------- /第3章 对象/原型.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | ```javascript 4 | var empty_object = {}; 5 | 6 | var stooge = { 7 | "first-name": "Jerome", 8 | "last-name": "Howard" 9 | }; 10 | 11 | 12 | ==================================== 13 | var flight = { 14 | airline: "Oceanic", 15 | number: 815, 16 | departure: { 17 | IATA: "SYD", 18 | time: "2004-09-22 14:55", 19 | city: "Sydney" 20 | }, 21 | arrival: { 22 | IATA: "LAX", 23 | time: "2004-09-23 10:42", 24 | city: "Los Angeles" 25 | } 26 | }; 27 | ==================================== 28 | if (typeof Object.create !== 'function') { 29 | Object.create = function (o) { 30 | var F = function () {}; 31 | F.prototype = o; 32 | return new F(); 33 | }; 34 | } 35 | var another_stooge = Object.create(stooge); 36 | 37 | 38 | ==================================== 39 | another_stooge['first-name'] = 'Harry'; 40 | another_stooge['middle-name'] = 'Moses'; 41 | another_stooge.nickname = 'Moe'; 42 | 43 | 44 | ==================================== 45 | stooge.profession = 'actor'; 46 | another_stooge.profession // 'actor' 47 | 48 | ``` 49 | -------------------------------------------------------------------------------- /第3章 对象/反射.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | ```javascript 4 | var empty_object = {}; 5 | 6 | var stooge = { 7 | "first-name": "Jerome", 8 | "last-name": "Howard" 9 | }; 10 | 11 | 12 | ==================================== 13 | var flight = { 14 | airline: "Oceanic", 15 | number: 815, 16 | departure: { 17 | IATA: "SYD", 18 | time: "2004-09-22 14:55", 19 | city: "Sydney" 20 | }, 21 | arrival: { 22 | IATA: "LAX", 23 | time: "2004-09-23 10:42", 24 | city: "Los Angeles" 25 | } 26 | }; 27 | ==================================== 28 | typeof flight.number // 'number' 29 | typeof flight.status // 'string' 30 | typeof flight.arrival // 'object' 31 | typeof flight.manifest // 'undefined' 32 | 33 | 34 | ==================================== 35 | typeof flight.toString // 'function' 36 | typeof flight.constructor // 'function' 37 | 38 | 39 | ==================================== 40 | flight.hasOwnProperty('number') // true 41 | flight.hasOwnProperty('constructor') // false 42 | 43 | ``` 44 | -------------------------------------------------------------------------------- /第3章 对象/对象字面量.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | ```javascript 4 | var empty_object = {}; 5 | 6 | var stooge = { 7 | "first-name": "Jerome", 8 | "last-name": "Howard" 9 | }; 10 | 11 | 12 | ==================================== 13 | var flight = { 14 | airline: "Oceanic", 15 | number: 815, 16 | departure: { 17 | IATA: "SYD", 18 | time: "2004-09-22 14:55", 19 | city: "Sydney" 20 | }, 21 | arrival: { 22 | IATA: "LAX", 23 | time: "2004-09-23 10:42", 24 | city: "Los Angeles" 25 | } 26 | }; 27 | ``` 28 | -------------------------------------------------------------------------------- /第3章 对象/引用.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | ```javascript 4 | var x = stooge; 5 | x.nickname = 'Curly'; 6 | var nick = stooge.nickname; 7 | // nick is 'Curly' because x and stooge 8 | // are references to the same object 9 | 10 | var a = {}, b = {}, c = {}; 11 | // a, b, and c each refer to a 12 | // different empty object 13 | a = b = c = {}; 14 | // a, b, and c all refer to 15 | // the same empty object 16 | 17 | ``` 18 | -------------------------------------------------------------------------------- /第3章 对象/更新.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | ```javascript 4 | stooge['first-name'] = 'Jerome'; 5 | 6 | 7 | ==================================== 8 | stooge['middle-name'] = 'Lester'; 9 | stooge.nickname = 'Curly'; 10 | flight.equipment = { 11 | model: 'Boeing 777' 12 | }; 13 | flight.status = 'overdue'; 14 | 15 | ``` 16 | -------------------------------------------------------------------------------- /第3章 对象/枚举.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | ```javascript 4 | var empty_object = {}; 5 | 6 | var stooge = { 7 | "first-name": "Jerome", 8 | "last-name": "Howard" 9 | }; 10 | 11 | 12 | ==================================== 13 | var flight = { 14 | airline: "Oceanic", 15 | number: 815, 16 | departure: { 17 | IATA: "SYD", 18 | time: "2004-09-22 14:55", 19 | city: "Sydney" 20 | }, 21 | arrival: { 22 | IATA: "LAX", 23 | time: "2004-09-23 10:42", 24 | city: "Los Angeles" 25 | } 26 | }; 27 | 28 | 29 | 30 | 31 | ==================================== 32 | var name; 33 | for (name in another_stooge) { 34 | if (typeof another_stooge[name] !== 'function') { 35 | document.writeln(name + ': ' + another_stooge[name]); 36 | } 37 | } 38 | 39 | 40 | ==================================== 41 | var i; 42 | var properties = [ 43 | 'first-name', 44 | 'middle-name', 45 | 'last-name', 46 | 'profession' 47 | ]; 48 | for (i = 0; i < properties.length; i += 1) { 49 | document.writeln(properties[i] + ': ' + 50 | another_stooge[properties[i]]); 51 | } 52 | 53 | ``` 54 | -------------------------------------------------------------------------------- /第3章 对象/检索.md: -------------------------------------------------------------------------------- 1 | chapter: Objects 2 | ================== 3 | 4 | ```javascript 5 | stooge["first-name"] // "Jerome" 6 | flight.departure.IATA // "SYD" 7 | 8 | 9 | ==================================== 10 | stooge["middle-name"] // undefined 11 | flight.status // undefined 12 | stooge["FIRST-NAME"] // undefined 13 | 14 | 15 | ==================================== 16 | var middle = stooge["middle-name"] || "(none)"; 17 | var status = flight.status || "unknown"; 18 | 19 | 20 | ==================================== 21 | flight.equipment // undefined 22 | flight.equipment.model // throw "TypeError" 23 | flight.equipment && flight.equipment.model // undefined 24 | 25 | ``` 26 | -------------------------------------------------------------------------------- /第4章 函数/作用域.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | var foo = function ( ) { 5 | var a = 3, b = 5; 6 | 7 | var bar = function ( ) { 8 | var b = 7, c = 11; 9 | 10 | // At this point, a is 3, b is 7, and c is 11 11 | 12 | a += b + c; 13 | 14 | // At this point, a is 21, b is 7, and c is 11 15 | 16 | }; 17 | 18 | // At this point, a is 3, b is 5, and c is not defined 19 | 20 | bar( ); 21 | 22 | // At this point, a is 21, b is 5 23 | 24 | }; 25 | 26 | 27 | ``` -------------------------------------------------------------------------------- /第4章 函数/函数字面量.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | // Create a variable called add and store a function 5 | // in it that adds two numbers. 6 | 7 | var add = function (a, b) { 8 | return a + b; 9 | }; 10 | 11 | ``` 12 | -------------------------------------------------------------------------------- /第4章 函数/函数对象.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | -------------------------------------------------------------------------------- /第4章 函数/参数.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | // Make a function that adds a lot of stuff. 5 | 6 | // Note that defining the variable sum inside of 7 | // the function does not interfere with the sum 8 | // defined outside of the function. The function 9 | // only sees the inner one. 10 | 11 | var sum = function ( ) { 12 | var i, sum = 0; 13 | for (i = 0; i < arguments.length; i += 1) { 14 | sum += arguments[i]; 15 | } 16 | return sum; 17 | }; 18 | 19 | document.writeln(sum(4, 8, 15, 16, 23, 42)); // 108 20 | 21 | ``` -------------------------------------------------------------------------------- /第4章 函数/回调.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | request = prepare_the_request( ); 5 | response = send_request_synchronously(request); 6 | display(response); 7 | 8 | 9 | ==================================== 10 | request = prepare_the_request( ); 11 | send_request_asynchronously(request, function (response) { 12 | display(response); 13 | }); 14 | 15 | ``` 16 | -------------------------------------------------------------------------------- /第4章 函数/异常.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | ==================================== 5 | var add = function (a, b) { 6 | if (typeof a !== 'number' || typeof b !== 'number') { 7 | throw { 8 | name: 'TypeError', 9 | message: 'add needs numbers' 10 | }; 11 | } 12 | return a + b; 13 | } 14 | 15 | ==================================== 16 | // Make a try_it function that calls the new add 17 | // function incorrectly. 18 | 19 | var try_it = function ( ) { 20 | try { 21 | add("seven"); 22 | } catch (e) { 23 | document.writeln(e.name + ': ' + e.message); 24 | } 25 | } 26 | 27 | try_it( ); 28 | ``` -------------------------------------------------------------------------------- /第4章 函数/扩充类型的功能.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | Function.prototype.method = function (name, func) { 5 | this.prototype[name] = func; 6 | return this; 7 | }; 8 | 9 | 10 | ==================================== 11 | Number.method('integer', function ( ) { 12 | return Math[this < 0 ? 'ceil' : 'floor'](this); 13 | }); 14 | 15 | document.writeln((-10 / 3).integer( )); // -3 16 | 17 | 18 | ==================================== 19 | String.method('trim', function ( ) { 20 | return this.replace(/^\s+|\s+$/g, ''); 21 | }); 22 | 23 | document.writeln('"' + " neat ".trim( ) + '"'); 24 | 25 | 26 | ==================================== 27 | // Add a method conditionally. 28 | 29 | Function.prototype.method = function (name, func) { 30 | if (!this.prototype[name]) { 31 | this.prototype[name] = func; 32 | return this; 33 | } 34 | }; 35 | 36 | 37 | ``` -------------------------------------------------------------------------------- /第4章 函数/柯里化.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | var add1 = add.curry(1); 5 | document.writeln(add1(6)); // 7 6 | 7 | 8 | ==================================== 9 | Function.method('curry', function ( ) { 10 | var args = arguments, that = this; 11 | return function ( ) { 12 | return that.apply(null, args.concat(arguments)); 13 | }; 14 | }); // Something isn't right... 15 | 16 | 17 | ==================================== 18 | Function.method('curry', function ( ) { 19 | var slice = Array.prototype.slice, 20 | args = slice.apply(arguments), 21 | that = this; 22 | return function ( ) { 23 | return that.apply(null, args.concat(slice.apply(arguments))); 24 | }; 25 | }); 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /第4章 函数/模块.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | String.method('deentityify', function ( ) { 5 | 6 | // The entity table. It maps entity names to 7 | // characters. 8 | 9 | var entity = { 10 | quot: '"', 11 | lt: '<', 12 | gt: '>' 13 | }; 14 | 15 | // Return the deentityify method. 16 | 17 | return function ( ) { 18 | 19 | // This is the deentityify method. It calls the string 20 | // replace method, looking for substrings that start 21 | // with '&' and end with ';'. If the characters in 22 | // between are in the entity table, then replace the 23 | // entity with the character from the table. It uses 24 | // a regular expression (Chapter 7). 25 | 26 | return this.replace(/&([^&;]+);/g, 27 | function (a, b) { 28 | var r = entity[b]; 29 | return typeof r === 'string' ? r : a; 30 | } 31 | ); 32 | }; 33 | }( )); 34 | 35 | 36 | ==================================== 37 | document.writeln( 38 | '<">'.deentityify( )); // <"> 39 | 40 | 41 | ==================================== 42 | var serial_maker = function ( ) { 43 | 44 | // Produce an object that produces unique strings. A 45 | // unique string is made up of two parts: a prefix 46 | // and a sequence number. The object comes with 47 | // methods for setting the prefix and sequence 48 | // number, and a gensym method that produces unique 49 | // strings. 50 | 51 | var prefix = ''; 52 | var seq = 0; 53 | return { 54 | set_prefix: function (p) { 55 | prefix = String(p); 56 | }, 57 | set_seq: function (s) { 58 | seq = s; 59 | }, 60 | gensym: function ( ) { 61 | var result = prefix + seq; 62 | seq += 1; 63 | return result; 64 | } 65 | }; 66 | }; 67 | var seqer = serial_maker( ); 68 | seqer.set_prefix('Q'); 69 | seqer.set_seq(1000); 70 | var unique = seqer.gensym( ); // unique is "Q1000" 71 | 72 | 73 | ``` -------------------------------------------------------------------------------- /第4章 函数/级联.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | getElement('myBoxDiv') 5 | .move(350, 150) 6 | .width(100) 7 | .height(100) 8 | .color('red') 9 | .border('10px outset') 10 | .padding('4px') 11 | .appendText("Please stand by") 12 | .on('mousedown', function (m) { 13 | this.startDrag(m, this.getNinth(m)); 14 | }). 15 | .on('mousemove', 'drag') 16 | .on('mouseup', 'stopDrag') 17 | .later(2000, function ( ) { 18 | this 19 | .color('yellow') 20 | .setHTML("What hath God wraught?") 21 | .slide(400, 40, 200, 200); 22 | }) 23 | .tip("This box is resizeable"); 24 | 25 | ``` 26 | -------------------------------------------------------------------------------- /第4章 函数/记忆.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | var fibonacci = function (n) { 5 | return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); 6 | }; 7 | 8 | for (var i = 0; i <= 10; i += 1) { 9 | document.writeln('// ' + i + ': ' + fibonacci(i)); 10 | } 11 | 12 | // 0: 0 13 | // 1: 1 14 | // 2: 1 15 | // 3: 2 16 | // 4: 3 17 | // 5: 5 18 | // 6: 8 19 | // 7: 13 20 | // 8: 21 21 | // 9: 34 22 | // 10: 55 23 | 24 | 25 | ==================================== 26 | var fibonacci = (function ( ) { 27 | var memo = [0, 1]; 28 | var fib = function (n) { 29 | var result = memo[n]; 30 | if (typeof result !== 'number') { 31 | result = fib(n - 1) + fib(n - 2); 32 | memo[n] = result; 33 | } 34 | return result; 35 | }; 36 | return fib; 37 | }( )); 38 | 39 | 40 | ==================================== 41 | var memoizer = function (memo, formula) { 42 | var recur = function (n) { 43 | var result = memo[n]; 44 | if (typeof result !== 'number') { 45 | result = formula(recur, n); 46 | memo[n] = result; 47 | } 48 | return result; 49 | }; 50 | return recur; 51 | }; 52 | 53 | 54 | ==================================== 55 | var fibonacci = memoizer([0, 1], function (recur, n) { 56 | return recur(n - 1) + recur(n - 2); 57 | }); 58 | 59 | 60 | ==================================== 61 | var factorial = memoizer([1, 1], function (recur, n) { 62 | return n * recur(n - 1); 63 | }); 64 | 65 | 66 | ``` -------------------------------------------------------------------------------- /第4章 函数/调用.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | // Create a variable called add and store a function 5 | // in it that adds two numbers. 6 | 7 | var add = function (a, b) { 8 | return a + b; 9 | }; 10 | 11 | 12 | ==================================== 13 | // Create myObject. It has a value and an increment 14 | // method. The increment method takes an optional 15 | // parameter. If the argument is not a number, then 1 16 | // is used as the default. 17 | 18 | var myObject = { 19 | value: 0, 20 | increment: function (inc) { 21 | this.value += typeof inc === 'number' ? inc : 1; 22 | } 23 | }; 24 | 25 | myObject.increment( ); 26 | document.writeln(myObject.value); // 1 27 | 28 | myObject.increment(2); 29 | document.writeln(myObject.value); // 3 30 | 31 | 32 | ==================================== 33 | var sum = add(3, 4); // sum is 7 34 | 35 | 36 | ==================================== 37 | // Augment myObject with a double method. 38 | 39 | myObject.double = function ( ) { 40 | var that = this; // Workaround. 41 | 42 | var helper = function ( ) { 43 | that.value = add(that.value, that.value); 44 | }; 45 | 46 | helper( ); // Invoke helper as a function. 47 | }; 48 | 49 | // Invoke double as a method. 50 | 51 | myObject.double( ); 52 | document.writeln(myObject.value); // 6 53 | 54 | 55 | ==================================== 56 | // Create a constructor function called Quo. 57 | // It makes an object with a status property. 58 | 59 | var Quo = function (string) { 60 | this.status = string; 61 | }; 62 | 63 | // Give all instances of Quo a public method 64 | // called get_status. 65 | 66 | Quo.prototype.get_status = function ( ) { 67 | return this.status; 68 | }; 69 | 70 | // Make an instance of Quo. 71 | 72 | var myQuo = new Quo("confused"); 73 | 74 | document.writeln(myQuo.get_status( )); // confused 75 | 76 | 77 | ==================================== 78 | // Make an array of 2 numbers and add them. 79 | 80 | var array = [3, 4]; 81 | var sum = add.apply(null, array); // sum is 7 82 | 83 | // Make an object with a status member. 84 | 85 | var statusObject = { 86 | status: 'A-OK' 87 | }; 88 | 89 | // statusObject does not inherit from Quo.prototype, 90 | // but we can invoke the get_status method on 91 | // statusObject even though statusObject does not have 92 | // a get_status method. 93 | 94 | var status = Quo.prototype.get_status.apply(statusObject); 95 | // status is 'A-OK' 96 | 97 | ``` -------------------------------------------------------------------------------- /第4章 函数/返回.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== -------------------------------------------------------------------------------- /第4章 函数/递归.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | var hanoi = function hanoi(disc, src, aux, dst) { 5 | if (disc > 0) { 6 | hanoi(disc - 1, src, dst, aux); 7 | document.writeln('Move disc ' + disc + 8 | ' from ' + src + ' to ' + dst); 9 | hanoi(disc - 1, aux, src, dst); 10 | } 11 | }; 12 | 13 | hanoi(3, 'Src', 'Aux', 'Dst'); 14 | 15 | 16 | ==================================== 17 | Move disc 1 from Src to Dst 18 | Move disc 2 from Src to Aux 19 | Move disc 1 from Dst to Aux 20 | Move disc 3 from Src to Dst 21 | Move disc 1 from Aux to Src 22 | Move disc 2 from Aux to Dst 23 | Move disc 1 from Src to Dst 24 | 25 | 26 | ==================================== 27 | // Define a walk_the_DOM function that visits every 28 | // node of the tree in HTML source order, starting 29 | // from some given node. It invokes a function, 30 | // passing it each node in turn. walk_the_DOM calls 31 | // itself to process each of the child nodes. 32 | 33 | var walk_the_DOM = function walk(node, func) { 34 | func(node); 35 | node = node.firstChild; 36 | while (node) { 37 | walk(node, func); 38 | node = node.nextSibling; 39 | } 40 | }; 41 | 42 | // Define a getElementsByAttribute function. It 43 | // takes an attribute name string and an optional 44 | // matching value. It calls walk_the_DOM, passing it a 45 | // function that looks for an attribute name in the 46 | // node. The matching nodes are accumulated in a 47 | // results array. 48 | 49 | var getElementsByAttribute = function (att, value) { 50 | var results = []; 51 | 52 | walk_the_DOM(document.body, function (node) { 53 | var actual = node.nodeType === 1 && node.getAttribute(att); 54 | if (typeof actual === 'string' && 55 | (actual === value || typeof value !== 'string')) { 56 | results.push(node); 57 | } 58 | }); 59 | 60 | return results; 61 | }; 62 | 63 | 64 | ==================================== 65 | // Make a factorial function with tail 66 | // recursion. It is tail recursive because 67 | // it returns the result of calling itself. 68 | 69 | // JavaScript does not currently optimize this form. 70 | 71 | var factorial = function factorial(i, a) { 72 | a = a || 1; 73 | if (i < 2) { 74 | return a; 75 | } 76 | return factorial(i - 1, a * i); 77 | }; 78 | 79 | document.writeln(factorial(4)); // 24 80 | 81 | ``` 82 | -------------------------------------------------------------------------------- /第4章 函数/闭包.md: -------------------------------------------------------------------------------- 1 | chapter: Functions 2 | ================== 3 | ```javascript 4 | var myObject = (function () { 5 | var value = 0; 6 | 7 | return { 8 | increment: function (inc) { 9 | value += typeof inc === 'number' ? inc : 1; 10 | }, 11 | getValue: function ( ) { 12 | return value; 13 | } 14 | }; 15 | }()); 16 | 17 | 18 | ==================================== 19 | // Create a maker function called quo. It makes an 20 | // object with a get_status method and a private 21 | // status property. 22 | 23 | var quo = function (status) { 24 | return { 25 | get_status: function ( ) { 26 | return status; 27 | } 28 | }; 29 | }; 30 | 31 | // Make an instance of quo. 32 | 33 | var myQuo = quo("amazed"); 34 | 35 | document.writeln(myQuo.get_status( )); 36 | 37 | 38 | ==================================== 39 | // Define a function that sets a DOM node's color 40 | // to yellow and then fades it to white. 41 | 42 | var fade = function (node) { 43 | var level = 1; 44 | var step = function ( ) { 45 | var hex = level.toString(16); 46 | node.style.backgroundColor = '#FFFF' + hex + hex; 47 | if (level < 15) { 48 | level += 1; 49 | setTimeout(step, 100); 50 | } 51 | }; 52 | setTimeout(step, 100); 53 | }; 54 | 55 | fade(document.body); 56 | 57 | 58 | ==================================== 59 | // BAD EXAMPLE 60 | 61 | // Make a function that assigns event handler functions to an array 62 | of nodes the wrong way. 63 | // When you click on a node, an alert box is supposed to display the ordinal 64 | of the node. 65 | // But it always displays the number of nodes instead. 66 | 67 | var add_the_handlers = function (nodes) { 68 | var i; 69 | for (i = 0; i < nodes.length; i += 1) { 70 | nodes[i].onclick = function (e) { 71 | alert(i); 72 | }; 73 | } 74 | }; 75 | 76 | // END BAD EXAMPLE 77 | 78 | 79 | ==================================== 80 | // BETTER EXAMPLE 81 | 82 | // Make a function that assigns event handler functions to an array of nodes. 83 | // When you click on a node, an alert box will display the ordinal of the node. 84 | 85 | var add_the_handlers = function (nodes) { 86 | var helper = function (i) { 87 | return function (e) { 88 | alert(i); 89 | }; 90 | }; 91 | var i; 92 | for (i = 0; i < nodes.length; i += 1) { 93 | modes[i].onclick = helper(i); 94 | } 95 | }; 96 | 97 | ``` 98 | -------------------------------------------------------------------------------- /第5章 继承/伪类.md: -------------------------------------------------------------------------------- 1 | chapter: Inheritance 2 | ================== 3 | ```javascript 4 | this.prototype = {constructor: this}; 5 | 6 | 7 | ==================================== 8 | Function.method('new', function ( ) { 9 | 10 | // Create a new object that inherits from the 11 | // constructor's prototype. 12 | 13 | var that = Object.beget(this.prototype); 14 | 15 | // Invoke the constructor, binding -this- to 16 | // the new object. 17 | 18 | var other = this.apply(that, arguments); 19 | 20 | // If its return value isn't an object, 21 | // substitute the new object. 22 | 23 | return (typeof other === 'object' && other) || that; 24 | }); 25 | 26 | 27 | ==================================== 28 | var Mammal = function (name) { 29 | this.name = name; 30 | }; 31 | 32 | Mammal.prototype.get_name = function ( ) { 33 | return this.name; 34 | }; 35 | 36 | Mammal.prototype.says = function ( ) { 37 | return this.saying || ''; 38 | }; 39 | 40 | 41 | ==================================== 42 | var myMammal = new Mammal('Herb the Mammal'); 43 | var name = myMammal.get_name( ); // 'Herb the Mammal' 44 | 45 | 46 | ==================================== 47 | var Cat = function (name) { 48 | this.name = name; 49 | this.saying = 'meow'; 50 | }; 51 | 52 | // Replace Cat.prototype with a new instance of Mammal 53 | 54 | Cat.prototype = new Mammal( ); 55 | 56 | // Augment the new prototype with 57 | // purr and get_name methods. 58 | 59 | Cat.prototype.purr = function (n) { 60 | var i, s = ''; 61 | for (i = 0; i < n; i += 1) { 62 | if (s) { 63 | s += '-'; 64 | } 65 | s += 'r'; 66 | } 67 | return s; 68 | }; 69 | Cat.prototype.get_name = function ( ) { 70 | return this.says( ) + ' ' + this.name + ' ' + this.says( ); 71 | }; 72 | 73 | var myCat = new Cat('Henrietta'); 74 | var says = myCat.says( ); // 'meow' 75 | var purr = myCat.purr(5); // 'r-r-r-r-r' 76 | var name = myCat.get_name( ); 77 | // 'meow Henrietta meow' 78 | 79 | 80 | ==================================== 81 | Function.method('inherits', function (Parent) { 82 | this.prototype = new Parent( ); 83 | return this; 84 | }); 85 | 86 | 87 | ==================================== 88 | var Cat = function (name) { 89 | this.name = name; 90 | this.saying = 'meow'; 91 | }. 92 | inherits(Mammal). 93 | method('purr', function (n) { 94 | var i, s = ''; 95 | for (i = 0; i < n; i += 1) { 96 | if (s) { 97 | s += '-'; 98 | } 99 | s += 'r'; 100 | } 101 | return s; 102 | }). 103 | method('get_name', function ( ) { 104 | return this.says( ) + ' ' + this.name + ' ' + this.says( ); 105 | }); 106 | 107 | ``` 108 | -------------------------------------------------------------------------------- /第5章 继承/函数化.md: -------------------------------------------------------------------------------- 1 | chapter: Inheritance 2 | ================== 3 | ```javascript 4 | var constructor = function (spec, my) { 5 | var that, other private instance variables; 6 | my = my || {}; 7 | 8 | Add shared variables and functions to my 9 | 10 | that = a new object; 11 | 12 | Add privileged methods to that 13 | 14 | return that; 15 | }; 16 | 17 | 18 | ==================================== 19 | my.member = value; 20 | 21 | 22 | ==================================== 23 | var methodical = function ( ) { 24 | ... 25 | }; 26 | that.methodical = methodical; 27 | 28 | 29 | ==================================== 30 | var mammal = function (spec) { 31 | var that = {}; 32 | 33 | that.get_name = function ( ) { 34 | return spec.name; 35 | }; 36 | 37 | that.says = function ( ) { 38 | return spec.saying || ''; 39 | }; 40 | 41 | return that; 42 | }; 43 | 44 | var myMammal = mammal({name: 'Herb'}); 45 | 46 | 47 | ==================================== 48 | var cat = function (spec) { 49 | spec.saying = spec.saying || 'meow'; 50 | var that = mammal(spec); 51 | that.purr = function (n) { 52 | var i, s = ''; 53 | for (i = 0; i < n; i += 1) { 54 | if (s) { 55 | s += '-'; 56 | } 57 | s += 'r'; 58 | } 59 | return s; 60 | }; 61 | that.get_name = function () { 62 | return that.says() + ' ' + spec.name + ' ' + that.says(); 63 | }; 64 | return that; 65 | }; 66 | 67 | var myCat = cat({name: 'Henrietta'}); 68 | 69 | 70 | ==================================== 71 | Object.method('superior', function (name) { 72 | var that = this, 73 | method = that[name]; 74 | return function ( ) { 75 | return method.apply(that, arguments); 76 | }; 77 | }); 78 | 79 | 80 | ==================================== 81 | var coolcat = function (spec) { 82 | var that = cat(spec), 83 | super_get_name = that.superior('get_name'); 84 | that.get_name = function (n) { 85 | return 'like ' + super_get_name( ) + ' baby'; 86 | }; 87 | return that; 88 | }; 89 | 90 | var myCoolCat = coolcat({name: 'Bix'}); 91 | var name = myCoolCat.get_name( ); 92 | // 'like meow Bix meow baby' 93 | 94 | ``` 95 | -------------------------------------------------------------------------------- /第5章 继承/原型.md: -------------------------------------------------------------------------------- 1 | chapter: Inheritance 2 | ================== 3 | ```javascript 4 | var myMammal = { 5 | name : 'Herb the Mammal', 6 | get_name : function ( ) { 7 | return this.name; 8 | }, 9 | says : function ( ) { 10 | return this.saying || ''; 11 | } 12 | }; 13 | 14 | 15 | ==================================== 16 | var myCat = Object.create(myMammal); 17 | myCat.name = 'Henrietta'; 18 | myCat.saying = 'meow'; 19 | myCat.purr = function (n) { 20 | var i, s = ''; 21 | for (i = 0; i < n; i += 1) { 22 | if (s) { 23 | s += '-'; 24 | } 25 | s += 'r'; 26 | } 27 | return s; 28 | }; 29 | myCat.get_name = function ( ) { 30 | return this.says() + ' ' + this.name + ' ' + this.says(); 31 | }; 32 | 33 | 34 | ==================================== 35 | var block = function ( ) { 36 | 37 | // Remember the current scope. Make a new scope that 38 | // includes everything from the current one. 39 | 40 | var oldScope = scope; 41 | scope = Object.create(scope); 42 | 43 | // Advance past the left curly brace. 44 | 45 | advance('{'); 46 | 47 | // Parse using the new scope. 48 | 49 | parse(scope); 50 | 51 | // Advance past the right curly brace and discard the 52 | // new scope, restoring the old one. 53 | 54 | advance('}'); 55 | scope = oldScope; 56 | }; 57 | 58 | 59 | ``` -------------------------------------------------------------------------------- /第5章 继承/对象说明符.md: -------------------------------------------------------------------------------- 1 | chapter: Inheritance 2 | ================== 3 | ```javascript 4 | var myObject = maker(f, l, m, c, s); 5 | 6 | 7 | ==================================== 8 | var myObject = maker({ 9 | first: f, 10 | last: l, 11 | middle: m 12 | state: s, 13 | city: c 14 | }); 15 | 16 | ``` 17 | -------------------------------------------------------------------------------- /第5章 继承/部件.md: -------------------------------------------------------------------------------- 1 | chapter: Inheritance 2 | ================== 3 | ```javascript 4 | var eventuality = function (that) { 5 | var registry = {}; 6 | 7 | that.fire = function (event) { 8 | 9 | // Fire an event on an object. The event can be either 10 | // a string containing the name of the event or an 11 | // object containing a type property containing the 12 | // name of the event. Handlers registered by the 'on' 13 | // method that match the event name will be invoked. 14 | 15 | var array, 16 | func, 17 | handler, 18 | i, 19 | type = typeof event === 'string' ? event : event.type; 20 | 21 | // If an array of handlers exist for this event, then 22 | // loop through it and execute the handlers in order. 23 | 24 | if (registry.hasOwnProperty(type)) { 25 | array = registry[type]; 26 | for (i = 0; i < array.length; i += 1) { 27 | handler = array[i]; 28 | 29 | // A handler record contains a method and an optional 30 | // array of parameters. If the method is a name, look 31 | // up the function. 32 | 33 | func = handler.method; 34 | if (typeof func === 'string') { 35 | func = this[func]; 36 | } 37 | 38 | // Invoke a handler. If the record contained 39 | // parameters, then pass them. Otherwise, pass the 40 | // event object. 41 | 42 | func.apply(this, 43 | handler.parameters || [event]); 44 | } 45 | } 46 | return this; 47 | }; 48 | 49 | that.on = function (type, method, parameters) { 50 | 51 | // Register an event. Make a handler record. Put it 52 | // in a handler array, making one if it doesn't yet 53 | // exist for this type. 54 | 55 | var handler = { 56 | method: method, 57 | parameters: parameters 58 | }; 59 | if (registry.hasOwnProperty(type)) { 60 | registry[type].push(handler); 61 | } else { 62 | registry[type] = [handler]; 63 | } 64 | return this; 65 | }; 66 | return that; 67 | }; 68 | 69 | 70 | ==================================== 71 | eventuality(that); 72 | 73 | 74 | ``` -------------------------------------------------------------------------------- /第6章 数组/删除.md: -------------------------------------------------------------------------------- 1 | chapter: Arrays 2 | ================== 3 | ```javascript 4 | var empty = []; 5 | var numbers = [ 6 | 'zero', 'one', 'two', 'three', 'four', 7 | 'five', 'six', 'seven', 'eight', 'nine' 8 | ]; 9 | 10 | 11 | 12 | delete numbers[2]; 13 | // numbers is ['zero', 'one', undefined, 'shi', 'go'] 14 | 15 | 16 | ==================================== 17 | numbers.splice(2, 1); 18 | // numbers is ['zero', 'one', 'shi', 'go'] 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /第6章 数组/容易混淆的地方.md: -------------------------------------------------------------------------------- 1 | chapter: Arrays 2 | ================== 3 | ```javascript 4 | var is_array = function (value) { 5 | return value && typeof value === 'object' && value.constructor === Array; 6 | }; 7 | 8 | 9 | ==================================== 10 | var is_array = function (value) { 11 | return Object.prototype.toString.apply(value) === '[object 12 | Array]'; 13 | }; 14 | 15 | ``` 16 | -------------------------------------------------------------------------------- /第6章 数组/指定初始值.md: -------------------------------------------------------------------------------- 1 | chapter: Arrays 2 | ================== 3 | ```javascript 4 | Array.dim = function (dimension, initial) { 5 | var a = [], i; 6 | for (i = 0; i < dimension; i += 1) { 7 | a[i] = initial; 8 | } 9 | return a; 10 | }; 11 | 12 | // Make an array containing 10 zeros. 13 | 14 | var myArray = Array.dim(10, 0); 15 | 16 | 17 | ==================================== 18 | var matrix = [ 19 | [0, 1, 2], 20 | [3, 4, 5], 21 | [6, 7, 8] 22 | ]; 23 | matrix[2][1] // 7 24 | 25 | 26 | ==================================== 27 | for (i = 0; i < n; i += 1) { 28 | my_array[i] = []; 29 | } 30 | 31 | // Note: Array.dim(n, []) will not work here. 32 | // Each element would get a reference to the same 33 | // array, which would be very bad. 34 | 35 | 36 | ==================================== 37 | Array.matrix = function (m, n, initial) { 38 | var a, i, j, mat = []; 39 | for (i = 0; i < m; i += 1) { 40 | a = []; 41 | for (j = 0; j < n; j += 1) { 42 | a[j] = initial; 43 | } 44 | mat[i] = a; 45 | } 46 | return mat; 47 | }; 48 | 49 | // Make a 4 * 4 matrix filled with zeros. 50 | 51 | var myMatrix = Array.matrix(4, 4, 0); 52 | 53 | document.writeln(myMatrix[3][3]); // 0 54 | 55 | // Method to make an identity matrix. 56 | 57 | Array.identity = function (n) { 58 | var i, mat = Array.matrix(n, n, 0); 59 | for (i = 0; i < n; i += 1) { 60 | mat[i][i] = 1; 61 | } 62 | return mat; 63 | }; 64 | 65 | myMatrix = Array.identity(4); 66 | 67 | document.writeln(myMatrix[3][3]); // 1 68 | 69 | 70 | ``` -------------------------------------------------------------------------------- /第6章 数组/数组字面量.md: -------------------------------------------------------------------------------- 1 | chapter: Arrays 2 | ================== 3 | ```javascript 4 | var empty = []; 5 | var numbers = [ 6 | 'zero', 'one', 'two', 'three', 'four', 7 | 'five', 'six', 'seven', 'eight', 'nine' 8 | ]; 9 | 10 | empty[1] // undefined 11 | numbers[1] // 'one' 12 | 13 | empty.length // 0 14 | numbers.length // 10 15 | 16 | 17 | ==================================== 18 | var numbers_object = { 19 | '0': 'zero', '1': 'one', '2': 'two', 20 | '3': 'three', '4': 'four', '5': 'five', 21 | '6': 'six', '7': 'seven', '8': 'eight', 22 | '9': 'nine' 23 | }; 24 | 25 | 26 | ==================================== 27 | var misc = [ 28 | 'string', 98.6, true, false, null, undefined, 29 | ['nested', 'array'], {object: true}, NaN, 30 | Infinity 31 | ]; 32 | misc.length // 10 33 | 34 | 35 | ``` -------------------------------------------------------------------------------- /第6章 数组/方法.md: -------------------------------------------------------------------------------- 1 | chapter: Arrays 2 | ================== 3 | ```javascript 4 | Array.method('reduce', function (f, value) { 5 | var i; 6 | for (i = 0; i < this.length; i += 1) { 7 | value = f(this[i], value); 8 | } 9 | return value; 10 | }); 11 | 12 | 13 | ==================================== 14 | // Create an array of numbers. 15 | 16 | var data = [4, 8, 15, 16, 23, 42]; 17 | 18 | // Define two simple functions. One will add two 19 | // numbers. The other will multiply two numbers. 20 | 21 | var add = function (a, b) { 22 | return a + b; 23 | }; 24 | 25 | var mult = function (a, b) { 26 | return a * b; 27 | }; 28 | 29 | // Invoke the data's reduce method, passing in the 30 | // add function. 31 | 32 | var sum = data.reduce(add, 0); // sum is 108 33 | 34 | // Invoke the reduce method again, this time passing 35 | // in the multiply function. 36 | 37 | var product = data.reduce(mult, 1); 38 | // product is 7418880 39 | 40 | 41 | ==================================== 42 | // Give the data array a total function. 43 | 44 | data.total = function ( ) { 45 | return this.reduce(add, 0); 46 | }; 47 | 48 | total = data.total( ); // total is 108 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /第6章 数组/枚举.md: -------------------------------------------------------------------------------- 1 | chapter: Arrays 2 | ================== 3 | ```javascript 4 | var myArray = []; 5 | myArray.length // 0 6 | 7 | myArray[1000000] = true; 8 | myArray.length // 1000001 9 | // myArray contains one property. 10 | 11 | 12 | 13 | var i; 14 | for (i = 0; i < myArray.length; i += 1) { 15 | document.writeln(myArray[i]); 16 | } 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /第6章 数组/长度.md: -------------------------------------------------------------------------------- 1 | chapter: Arrays 2 | ================== 3 | ```javascript 4 | var myArray = []; 5 | myArray.length // 0 6 | 7 | myArray[1000000] = true; 8 | myArray.length // 1000001 9 | // myArray contains one property. 10 | 11 | 12 | ==================================== 13 | numbers.length = 3; 14 | // numbers is ['zero', 'one', 'two'] 15 | 16 | 17 | ==================================== 18 | numbers[numbers.length] = 'shi'; 19 | // numbers is ['zero', 'one', 'two', 'shi'] 20 | 21 | 22 | ==================================== 23 | numbers.push('go'); 24 | // numbers is ['zero', 'one', 'two', 'shi', 'go'] 25 | 26 | ``` -------------------------------------------------------------------------------- /第7章 正则表达式/一个例子.md: -------------------------------------------------------------------------------- 1 | chapter: Regular Expressions 2 | ================== 3 | ```javascript 4 | var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+) 5 | (?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/; 6 | 7 | var url = "http://www.ora.com:80/goodparts?q#fragment"; 8 | 9 | 10 | ==================================== 11 | var url = "http://www.ora.com:80/goodparts?q#fragment"; 12 | 13 | var result = parse_url.exec(url); 14 | 15 | var names = ['url', 'scheme', 'slash', 'host', 'port', 16 | 'path', 'query', 'hash']; 17 | 18 | var blanks = ' '; 19 | var i; 20 | 21 | for (i = 0; i < names.length; i += 1) { 22 | document.writeln(names[i] + ':' + 23 | blanks.substring(names[i].length), result[i]); 24 | } 25 | 26 | 27 | ==================================== 28 | url: http://www.ora.com:80/goodparts?q#fragment 29 | scheme: http 30 | slash: // 31 | host: www.ora.com 32 | port: 80 33 | path: goodparts 34 | query: q 35 | hash: fragment 36 | 37 | 38 | ==================================== 39 | ^ 40 | 41 | 42 | ==================================== 43 | (?:([A-Za-z]+):)? 44 | 45 | 46 | ==================================== 47 | (\/{0,3}) 48 | 49 | 50 | ==================================== 51 | ([0-9.\-A-Za-z]+) 52 | 53 | 54 | ==================================== 55 | (?::(\d+))? 56 | 57 | 58 | ==================================== 59 | (?:\/([^?#]*))? 60 | 61 | 62 | ==================================== 63 | (?:\?([^#]*))? 64 | 65 | 66 | ==================================== 67 | (?:#(.*))? 68 | 69 | 70 | ==================================== 71 | $ 72 | 73 | 74 | ==================================== 75 | var parse_number = /^-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?$/i; 76 | 77 | var test = function (num) { 78 | document.writeln(parse_number.test(num)); 79 | }; 80 | 81 | test('1'); // true 82 | test('number'); // false 83 | test('98.6'); // true 84 | test('132.21.86.100'); // false 85 | test('123.45E-67'); // true 86 | test('123.45D-67'); // false 87 | 88 | 89 | ==================================== 90 | /^ $/i 91 | 92 | 93 | ==================================== 94 | -? 95 | 96 | 97 | ==================================== 98 | \d+ 99 | 100 | 101 | ==================================== 102 | (?:\.\d*)? 103 | 104 | 105 | ==================================== 106 | (?:e[+\-]?\d+)? 107 | 108 | ``` 109 | -------------------------------------------------------------------------------- /第7章 正则表达式/元素.md: -------------------------------------------------------------------------------- 1 | chapter: Regular Expressions 2 | ================== 3 | ```javascript 4 | "into".match(/in|int/) 5 | 6 | 7 | ==================================== 8 | \ / [ ] ( ) { } ? + * | . ^ $ 9 | 10 | 11 | ==================================== 12 | var doubled_words = /([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1/gi; 13 | 14 | 15 | ==================================== 16 | ! " # $ % & ' ( ) * +, - . / : 17 | ; < = > ? @ [ \ ] ^ _ ` { | } ˜ 18 | 19 | 20 | ==================================== 21 | (?:!|"|#|\$|%|&|'|\(|\)|\*|\+|,|-|\.|\/|:|;|<|=|>|@|\[|\\|]|\^|_|` |\{|\||\}|˜) 22 | 23 | 24 | ==================================== 25 | [!-\/:-@\[-`{-˜] 26 | 27 | 28 | ==================================== 29 | - / [ \ ] ^ 30 | 31 | 32 | ``` -------------------------------------------------------------------------------- /第7章 正则表达式/结构.md: -------------------------------------------------------------------------------- 1 | chapter: Regular Expressions 2 | ================== 3 | ```javascript 4 | // Make a regular expression object that matches 5 | // a JavaScript string. 6 | 7 | var my_regexp = /"(?:\\.|[^\\\"])*"/g; 8 | 9 | 10 | ==================================== 11 | // Make a regular expression object that matches 12 | // a JavaScript string. 13 | 14 | var my_regexp = new RegExp("\"(?:\\\\.|[^\\\\\\\"])*\"", 'g'); 15 | 16 | 17 | ==================================== 18 | function make_a_matcher( ) { 19 | return /a/gi; 20 | } 21 | 22 | var x = make_a_matcher( ); 23 | var y = make_a_matcher( ); 24 | 25 | // Beware: x and y are the same object! 26 | 27 | x.lastIndex = 10; 28 | 29 | document.writeln(y.lastIndex); // 10 30 | 31 | ``` 32 | -------------------------------------------------------------------------------- /第8章 方法/Array.md: -------------------------------------------------------------------------------- 1 | chapter: Methods 2 | ================== 3 | ```javascript 4 | var a = ['a', 'b', 'c']; 5 | var b = ['x', 'y', 'z']; 6 | var c = a.concat(b, true); 7 | // c is ['a', 'b', 'c', 'x', 'y', 'z', true] 8 | 9 | 10 | ==================================== 11 | var a = ['a', 'b', 'c']; 12 | a.push('d'); 13 | var c = a.join(''); // c is 'abcd'; 14 | 15 | 16 | ==================================== 17 | var a = ['a', 'b', 'c']; 18 | var c = a.pop( ); // a is ['a', 'b'] & c is 'c' 19 | 20 | 21 | ==================================== 22 | Array.method('pop', function ( ) { 23 | return this.splice(this.length - 1, 1)[0]; 24 | }); 25 | 26 | 27 | ==================================== 28 | var a = ['a', 'b', 'c']; 29 | var b = ['x', 'y', 'z']; 30 | var c = a.push(b, true); 31 | // a is ['a', 'b', 'c', ['x', 'y', 'z'], true] 32 | // c is 5; 33 | 34 | 35 | ==================================== 36 | Array.method('push', function ( ) { 37 | this.splice.apply( 38 | this, 39 | [this.length, 0].concat(Array.prototype.slice.apply(arguments))); 40 | return this.length; 41 | }); 42 | 43 | 44 | ==================================== 45 | var a = ['a', 'b', 'c']; 46 | var b = a.reverse( ); 47 | // both a and b are ['c', 'b', 'a'] 48 | 49 | 50 | ==================================== 51 | var a = ['a', 'b', 'c']; 52 | var c = a.shift( ); // a is ['b', 'c'] & c is 'a' 53 | 54 | 55 | ==================================== 56 | Array.method('shift', function ( ) { 57 | return this.splice(0, 1)[0]; 58 | }); 59 | 60 | 61 | ==================================== 62 | var a = ['a', 'b', 'c']; 63 | var b = a.slice(0, 1); // b is ['a'] 64 | var c = a.slice(1); // c is ['b', 'c'] 65 | var d = a.slice(1, 2); // d is ['b'] 66 | 67 | 68 | ==================================== 69 | var n = [4, 8, 15, 16, 23, 42]; 70 | n.sort( ); 71 | // n is [15, 16, 23, 4, 42, 8] 72 | 73 | 74 | ==================================== 75 | n.sort(function (a, b) { 76 | return a - b; 77 | }); 78 | // n is [4, 8, 15, 16, 23, 42]; 79 | 80 | 81 | ==================================== 82 | var m = ['aa', 'bb', 'a', 4, 8, 15, 16, 23, 42]; 83 | m.sort(function (a, b) { 84 | if (a === b) { 85 | return 0; 86 | } 87 | if (typeof a === typeof b) { 88 | return a < b ? -1 : 1; 89 | } 90 | return typeof a < typeof b ? -1 : 1; 91 | }); 92 | // m is [4, 8, 15, 16, 23, 42, 'a', 'aa', 'bb'] 93 | 94 | 95 | ==================================== 96 | // Function by takes a member name string and returns 97 | // a comparison function that can be used to sort an 98 | // array of objects that contain that member. 99 | 100 | var by = function (name) { 101 | return function (o, p) { 102 | var a, b; 103 | if (typeof o === 'object' && typeof p === 'object' && o && p) { 104 | a = o[name]; 105 | b = p[name]; 106 | if (a === b) { 107 | return 0; 108 | } 109 | if (typeof a === typeof b) { 110 | return a < b ? -1 : 1; 111 | } 112 | return typeof a < typeof b ? -1 : 1; 113 | } else { 114 | throw { 115 | name: 'Error', 116 | message: 'Expected an object when sorting by ' + name; 117 | }; 118 | } 119 | }; 120 | }; 121 | 122 | var s = [ 123 | {first: 'Joe', last: 'Besser'}, 124 | {first: 'Moe', last: 'Howard'}, 125 | {first: 'Joe', last: 'DeRita'}, 126 | {first: 'Shemp', last: 'Howard'}, 127 | {first: 'Larry', last: 'Fine'}, 128 | {first: 'Curly', last: 'Howard'} 129 | ]; 130 | s.sort(by('first')); // s is [ 131 | // {first: 'Curly', last: 'Howard'}, 132 | // {first: 'Joe', last: 'DeRita'}, 133 | // {first: 'Joe', last: 'Besser'}, 134 | // {first: 'Larry', last: 'Fine'}, 135 | // {first: 'Moe', last: 'Howard'}, 136 | // {first: 'Shemp', last: 'Howard'} 137 | // ] 138 | 139 | 140 | ==================================== 141 | s.sort(by('first')).sort(by('last')); 142 | 143 | 144 | ==================================== 145 | // Function by takes a member name string and an 146 | // optional minor comparison function and returns 147 | // a comparison function that can be used to sort an 148 | // array of objects that contain that member. The 149 | // minor comparison function is used to break ties 150 | // when the o[name] and p[name] are equal. 151 | 152 | var by = function (name, minor) { 153 | return function (o, p) { 154 | var a, b; 155 | if (o && p && typeof o === 'object' && typeof p === 'object') { 156 | a = o[name]; 157 | b = p[name]; 158 | if (a === b) { 159 | return typeof minor === 'function' ? minor(o, p) : 0; 160 | } 161 | if (typeof a === typeof b) { 162 | return a < b ? -1 : 1; 163 | } 164 | return typeof a < typeof b ? -1 : 1; 165 | } else { 166 | throw { 167 | name: 'Error', 168 | message: 'Expected an object when sorting by ' + name; 169 | }; 170 | } 171 | }; 172 | }; 173 | 174 | s.sort(by('last', by('first'))); // s is [ 175 | // {first: 'Joe', last: 'Besser'}, 176 | // {first: 'Joe', last: 'DeRita'}, 177 | // {first: 'Larry', last: 'Fine'}, 178 | // {first: 'Curly', last: 'Howard'}, 179 | // {first: 'Moe', last: 'Howard'}, 180 | // {first: 'Shemp', last: 'Howard'} 181 | // ] 182 | 183 | 184 | ==================================== 185 | var a = ['a', 'b', 'c']; 186 | var r = a.splice(1, 1, 'ache', 'bug'); 187 | // a is ['a', 'ache', 'bug', 'c'] 188 | // r is ['b'] 189 | 190 | 191 | ==================================== 192 | Array.method('splice', function (start, deleteCount) { 193 | var max = Math.max, 194 | min = Math.min, 195 | delta, 196 | element, 197 | insertCount = max(arguments.length - 2, 0), 198 | k = 0, 199 | len = this.length, 200 | new_len, 201 | result = [], 202 | shift_count; 203 | 204 | start = start || 0; 205 | if (start < 0) { 206 | start += len; 207 | } 208 | start = max(min(start, len), 0); 209 | deleteCount = max(min(typeof deleteCount === 'number' ? 210 | deleteCount : len, len - start), 0); 211 | delta = insertCount - deleteCount; 212 | new_len = len + delta; 213 | while (k < deleteCount) { 214 | element = this[start + k]; 215 | if (element !== undefined) { 216 | result[k] = element; 217 | } 218 | k += 1; 219 | } 220 | shift_count = len - start - deleteCount; 221 | if (delta < 0) { 222 | k = start + insertCount; 223 | while (shift_count) { 224 | this[k] = this[k - delta]; 225 | k += 1; 226 | shift_count -= 1; 227 | } 228 | this.length = new_len; 229 | } else if (delta > 0) { 230 | k = 1; 231 | while (shift_count) { 232 | this[new_len - k] = this[len - k]; 233 | k += 1; 234 | shift_count -= 1; 235 | } 236 | this.length = new_len; 237 | } 238 | for (k = 0; k < insertCount; k += 1) { 239 | this[start + k] = arguments[k + 2]; 240 | } 241 | return result; 242 | }); 243 | 244 | 245 | ==================================== 246 | var a = ['a', 'b', 'c']; 247 | var r = a.unshift('?', '@'); 248 | // a is ['?', '@', 'a', 'b', 'c'] 249 | // r is 5 250 | 251 | 252 | ==================================== 253 | Array.method('unshift', function ( ) { 254 | this.splice.apply(this, 255 | [0, 0].concat(Array.prototype.slice.apply(arguments))); 256 | return this.length; 257 | }); 258 | 259 | 260 | ``` -------------------------------------------------------------------------------- /第8章 方法/Function.md: -------------------------------------------------------------------------------- 1 | chapter: Methods 2 | ```javascript 3 | Function.method('bind', function (that) { 4 | 5 | // Return a function that will call this function as 6 | // though it is a method of that object. 7 | 8 | var method = this, 9 | slice = Array.prototype.slice, 10 | args = slice.apply(arguments, [1]); 11 | return function ( ) { 12 | return method.apply(that, 13 | args.concat(slice.apply(arguments, [0]))); 14 | }; 15 | }); 16 | 17 | var x = function ( ) { 18 | return this.value; 19 | }.bind({value: 666}); 20 | alert(x( )); // 666 21 | 22 | ``` 23 | -------------------------------------------------------------------------------- /第8章 方法/Number.md: -------------------------------------------------------------------------------- 1 | chapter: Methods 2 | ================== 3 | ```javascript 4 | document.writeln(Math.PI.toExponential(0)); 5 | document.writeln(Math.PI.toExponential(2)); 6 | document.writeln(Math.PI.toExponential(7)); 7 | document.writeln(Math.PI.toExponential(16)); 8 | document.writeln(Math.PI.toExponential( )); 9 | 10 | // Produces 11 | 12 | 3e+0 13 | 3.14e+0 14 | 3.1415927e+0 15 | 3.1415926535897930e+0 16 | 3.141592653589793e+0 17 | 18 | 19 | ==================================== 20 | document.writeln(Math.PI.toFixed(0)); 21 | document.writeln(Math.PI.toFixed(2)); 22 | document.writeln(Math.PI.toFixed(7)); 23 | document.writeln(Math.PI.toFixed(16)); 24 | document.writeln(Math.PI.toFixed( )); 25 | 26 | // Produces 27 | 28 | 3 29 | 3.14 30 | 3.1415927 31 | 3.1415926535897930 32 | 3 33 | 34 | 35 | ==================================== 36 | document.writeln(Math.PI.toPrecision(2)); 37 | document.writeln(Math.PI.toPrecision(7)); 38 | document.writeln(Math.PI.toPrecision(16)); 39 | document.writeln(Math.PI.toPrecision( )); 40 | 41 | // Produces 42 | 43 | 3.1 44 | 3.141593 45 | 3.141592653589793 46 | 3.141592653589793 47 | 48 | 49 | ==================================== 50 | document.writeln(Math.PI.toString(2)); 51 | document.writeln(Math.PI.toString(8)); 52 | document.writeln(Math.PI.toString(16)); 53 | document.writeln(Math.PI.toString( )); 54 | 55 | // Produces 56 | 57 | 11.001001000011111101101010100010001000010110100011 58 | 3.1103755242102643 59 | 3.243f6a8885a3 60 | 3.141592653589793 61 | 62 | ``` 63 | -------------------------------------------------------------------------------- /第8章 方法/Object.md: -------------------------------------------------------------------------------- 1 | chapter: Methods 2 | ================== 3 | ```javascript 4 | var a = {member: true}; 5 | var b = Object.create(a); // from Chapter 3 6 | var t = a.hasOwnProperty('member'); // t is true 7 | var u = b.hasOwnProperty('member'); // u is false 8 | var v = b.member; // v is true 9 | 10 | ``` -------------------------------------------------------------------------------- /第8章 方法/RegExp.md: -------------------------------------------------------------------------------- 1 | chapter: Methods 2 | ================== 3 | ```javascript 4 | // Break a simple html text into tags and texts. 5 | // (See string.replace for the entityify method.) 6 | 7 | // For each tag or text, produce an array containing 8 | // [0] The full matched tag or text 9 | // [1] The /, if there is one 10 | // [2] The tag name 11 | // [3] The attributes, if any 12 | 13 | var text = '' + 14 | 'This is bold<\/b>!<\/p><\/body><\/html>'; 15 | var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g; 16 | var a, i; 17 | 18 | while ((a = tags.exec(text))) { 19 | for (i = 0; i < a.length; i += 1) { 20 | document.writeln(('// [' + i + '] ' + a[i]).entityify( )); 21 | } 22 | document.writeln( ); 23 | } 24 | 25 | // Result: 26 | 27 | // [0] 28 | // [1] 29 | // [2] html 30 | // [3] 31 | 32 | // [0] 33 | // [1] 34 | // [2] body 35 | // [3] bgcolor=linen 36 | 37 | // [0]
38 | // [1] 39 | // [2] p 40 | // [3] 41 | 42 | // [0] This is 43 | // [1] undefined 44 | // [2] undefined 45 | // [3] undefined 46 | 47 | // [0] 48 | // [1] 49 | // [2] b 50 | // [3] 51 | 52 | // [0] bold 53 | // [1] undefined 54 | // [2] undefined 55 | // [3] undefined 56 | 57 | // [0] 58 | // [1] / 59 | // [2] b 60 | // [3] 61 | 62 | // [0] ! 63 | // [1] undefined 64 | // [2] undefined 65 | // [3] undefined 66 | 67 | // [0]
68 | // [1] / 69 | // [2] p 70 | // [3] 71 | 72 | // [0] 73 | // [1] / 74 | // [2] body 75 | // [3] 76 | 77 | // [0] 78 | // [1] / 79 | // [2] html 80 | // [3] 81 | 82 | 83 | ==================================== 84 | var b = /&.+;/.test('frank & beans'); 85 | // b is true 86 | 87 | 88 | ==================================== 89 | RegExp.method('test', function (string) { 90 | return this.exec(string) !== null; 91 | }); 92 | 93 | ``` -------------------------------------------------------------------------------- /第8章 方法/String.md: -------------------------------------------------------------------------------- 1 | chapter: Methods 2 | ================== 3 | ```javascript 4 | var name = 'Curly'; 5 | var initial = name.charAt(0); // initial is 'C' 6 | 7 | 8 | ==================================== 9 | String.method('charAt', function (pos) { 10 | return this.slice(pos, pos + 1); 11 | }); 12 | 13 | 14 | ==================================== 15 | var name = 'Curly'; 16 | var initial = name.charCodeAt(0); // initial is 67 17 | 18 | 19 | ==================================== 20 | var s = 'C'.concat('a', 't'); // s is 'Cat' 21 | 22 | 23 | ==================================== 24 | var text = 'Mississippi'; 25 | var p = text.indexOf('ss'); // p is 2 26 | p = text.indexOf('ss', 3); // p is 5 27 | p = text.indexOf('ss', 6); // p is -1 28 | 29 | 30 | ==================================== 31 | var text = 'Mississippi'; 32 | var p = text.lastIndexOf('ss'); // p is 5 33 | p = text.lastIndexOf('ss', 3); // p is 2 34 | p = text.lastIndexOf('ss', 6); // p is 5 35 | 36 | 37 | ==================================== 38 | var m = ['AAA', 'A', 'aa', 'a', 'Aa', 'aaa']; 39 | m.sort(function (a, b) { 40 | return a.localeCompare(b); 41 | }); 42 | // m (in some locale) is 43 | // ['a', 'A', 'aa', 'Aa', 'aaa', 'AAA'] 44 | 45 | 46 | ==================================== 47 | var text = '' + 48 | 'This is bold<\/b>!<\/p><\/body><\/html>'; 49 | var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g; 50 | var a, i; 51 | 52 | a = text.match(tags); 53 | for (i = 0; i < a.length; i += 1) { 54 | document.writeln(('// [' + i + '] ' + a[i]).entityify( )); 55 | } 56 | 57 | // The result is 58 | 59 | // [0] 60 | // [1] 61 | // [2]
62 | // [3] This is 63 | // [4] 64 | // [5] bold 65 | // [6] 66 | // [7] ! 67 | // [8]
68 | // [9] 69 | // [10] 70 | 71 | 72 | ==================================== 73 | var result = "mother_in_law".replace('_', '-'); 74 | 75 | 76 | ==================================== 77 | // Capture 3 digits within parens 78 | 79 | var oldareacode = /\((\d{3})\)/g; 80 | var p = '(555)666-1212'.replace(oldareacode, '$1-'); 81 | // p is '555-666-1212' 82 | 83 | 84 | ==================================== 85 | String.method('entityify', function ( ) { 86 | 87 | var character = { 88 | '<' : '<', 89 | '>' : '>', 90 | '&' : '&', 91 | '"' : '"' 92 | }; 93 | 94 | // Return the string.entityify method, which 95 | // returns the result of calling the replace method. 96 | // Its replaceValue function returns the result of 97 | // looking a character up in an object. This use of 98 | // an object usually outperforms switch statements. 99 | 100 | return function ( ) { 101 | return this.replace(/[<>&"]/g, function (c) { 102 | return character[c]; 103 | }); 104 | }; 105 | }( )); 106 | alert("<&>".entityify( )); // <&> 107 | 108 | 109 | ==================================== 110 | var text = 'and in it he says "Any damn fool could'; 111 | var pos = text.search(/["']/); // pos is 18 112 | 113 | 114 | ==================================== 115 | var text = 'and in it he says "Any damn fool could'; 116 | var a = text.slice(18); 117 | // a is '"Any damn fool could' 118 | var b = text.slice(0, 3); 119 | // b is 'and' 120 | var c = text.slice(-5); 121 | // c is 'could' 122 | var d = text.slice(19, 32); 123 | // d is 'Any damn fool' 124 | 125 | 126 | ==================================== 127 | var digits = '0123456789'; 128 | var a = digits.split('', 5); 129 | // a is ['0', '1', '2', '3', '4'] 130 | 131 | 132 | ==================================== 133 | var ip = '192.168.1.0'; 134 | var b = ip.split('.'); 135 | // b is ['192', '168', '1', '0'] 136 | 137 | var c = '|a|b|c|'.split('|'); 138 | // c is ['', 'a', 'b', 'c', ''] 139 | 140 | var text = 'last, first ,middle'; 141 | var d = text.split(/\s*,\s*/); 142 | // d is [ 143 | // 'last', 144 | // 'first', 145 | // 'middle' 146 | // ] 147 | 148 | 149 | ==================================== 150 | var e = text.split(/\s*(,)\s*/); 151 | // e is [ 152 | // 'last', 153 | // ',', 154 | // 'first', 155 | // ',', 156 | // 'middle' 157 | // ] 158 | 159 | 160 | ==================================== 161 | var f = '|a|b|c|'.split(/\|/); 162 | // f is ['a', 'b', 'c'] on some systems, and 163 | // f is ['', 'a', 'b', 'c', ''] on others 164 | 165 | 166 | ==================================== 167 | var a = String.fromCharCode(67, 97, 116); 168 | // a is 'Cat' 169 | 170 | 171 | ``` -------------------------------------------------------------------------------- /第9章 代码风格/ch09.md: -------------------------------------------------------------------------------- 1 | chapter: Style 2 | ================== 3 | ```javascript 4 | if (a) 5 | b( ); 6 | 7 | 8 | ==================================== 9 | if (a) 10 | b( ); 11 | c( ); 12 | 13 | 14 | ==================================== 15 | if (a) { 16 | b( ); 17 | c( ); 18 | } 19 | 20 | 21 | ==================================== 22 | if (a) { 23 | b( ); 24 | } 25 | c( ); 26 | 27 | 28 | ==================================== 29 | i = 0; // Set i to zero. 30 | 31 | 32 | ==================================== 33 | if (a = b) { ... } 34 | 35 | 36 | ==================================== 37 | if (a === b) { ... } 38 | 39 | 40 | ``` --------------------------------------------------------------------------------