//Javascript语言精粹 全书脚本Demo,可以用Firefox 的firebug运行每个demo
demo url:https://files.cnblogs.com/vihone/TheExcellenceInJavascript.rar
//3.5 原型 if(typeof Object.beget !== 'function') { Object.beget = function(o) { var F = function() {}; F.prototype = o; return new F(); }; }
var another_stooge = Object.beget(stooge); another_stooge['first-name'] = 'Vihone'; another_stooge['middle-name'] = 'He'; another_stooge.nickname = 'Moe';
//4.6 var add = function(a, b) { if(typeof a !== 'number' || typeof b !== 'number') { throw 'add needs numbers'; } return a + b; };
//4.7 Function.prototype.method = function(name,func) { this.prototype[name]=func; return this; };
Number.method('integer',function() { return Math[this<0 ? 'ceil':'floor'](this); });
var foo = function() { var a = 3, b=5; var bar = function() { var b = 7, c=11; a+=b+c; }; bar(); console.log(a); console.log(b); console.log(c); }; foo();
document.writeln((-10/3).integer());
var myObject = function() { var value = 0; return { increment: function(inc) { value += typeof inc === 'number' ? inc :1; }, getValue:function() { return value; } } }();
var quo = function(status) { return { get_status : function() { return status; } }; }; var myQuo = quo("amazed"); myQuo.get_status();
var fade = function() { node = document.body; 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); };
var add_the_handlers = function() { var nodes = document.getElementsByTagName("input"); var i ; for(i=0;i<nodes.length;i++) { nodes[i].onclick = function(i) { return function(e) { alert(e); } }(i); } };
//4.12 String.method('deentityify',function() { var entity = { quot:'"', lt:'<', gt:'>', };
return function() { return this.replace(/&([^&;]+);/g, function(a,b,c,d) { var r = entity[b]; //console.log(a); //a 依次为 < " > //console.log(b); //b 依次为 1t quot gt //console.log(c); //c 依次为 0 4 10 //console.log(d); //d 为stringObj --> <"> return typeof r === 'string' ? r : a; }); } }()); console.log('<">'.deentityify()); //replace方法的语法是:stringObj.replace(rgExp, replaceText) 其中stringObj是字符串(string),reExp可以是正则表达式对象(RegExp)也可以是字符串//(string),replaceText是替代查找到的字符串
//如果 replaceText 为函数,对于每一个匹配的子字符串,调用该函数时带有下面的 m+3 个参数,此处 m 是在 rgExp 中捕获的左括弧的个数。第一个参数是匹配的子字符//串。接下来的 m 个参数是查找中捕获的全部结果。第 m+2 个参数是在 stringObj 中匹配出现的偏移量,而第 m+3 个参数为 stringObj。结果为将每一匹配的子字符串替//换为函数调用的相应返回值的字符串值
//4.14 Function.method('curry',function() { var slice = Array.prototype.slice, args = slice.apply(arguments);//curry 的参数 //console.log(args); //[1] that = this; return function() { //console.log(slice.apply(arguments)); //[6] 当然的参数 return that.apply(null,args.concat(slice.apply(arguments))); }; });
//console.log(add.curry(1)(6)); //7 var add1 = add.curry(1); console.log(add1(6)); //7
//4.15 var count = 0; var fibonacci = function(n) { //return n < 2 ? n : fibonacci(n-1) + fibonacci(n-2); var memo = [0, 1]; var fib = function(n) { var result = memo[n]; count +=1; if(typeof result !== 'number') { result = fib(n-1) + fib(n-2); memo[n] = result; } return result; }; return fib; }();
var memoizer = function(memo, fundamental) { var shell = function(n) { var result = memo[n]; count +=1; if(typeof result !== 'number') { result = fundamental(shell, n); memo[n] = result; console.log(memo);//memo中存储每次计算后的值memo[0,1,1,2,3,5,8,13,21,34,55,...] } return result; }; return shell; };
//Fibonacci 数列 var fibonacci = memoizer([0, 1],function(shell, n) { return shell(n-1) + shell(n-2); });
//阶乘 var factorial = memoizer([0,1],function(shelll, n) { return n * shell(n-1); });
for(var i = 0; i <=10; i++) { console.log('//' + i + ': ' + fibonacci(i)); }
//第5章 继承
function foo(a, b, c) { return a*b*c; };
console.log(foo.length); //3 console.log(typeof foo.constructor); //function console.log(typeof foo.call); //function console.log(typeof foo.apply); //function console.log(typeof foo.prototype); //object
//对于任何一个函数的声明,它都将会具有上面所述的5个property(方法或者属性)。
//5.1 if(typeof Object.beget !== 'function') { Object.beget = function(o) { var F = function() {}; F.prototype = o; return new F(); }; }
Function.method('new',function() { var that = Object.beget(this.prototype);
var other = this.apply(that,arguments);
return (typeof other === 'object' && other) || that; });
var Mammal = function(name) { this.name = name; };
Mammal.prototype.get_name = function() { return this.name; };
Mammal.prototype.says = function() { return this.saying || ''; };
var myMammal = new Mammal('Herb the Mammal'); var name = myMammal.get_name(); console.log(name);
var Cat = function(name) { this.name = name; this.saying = 'meow'; };
Cat.prototype = new Mammal();
Cat.prototype.purr = function(n) { var i, s = ''; for(i = 0; i < n; i +=1) { if(s) { s += '-'; } s+= 'r'; } return s; };
Cat.prototype.get_name = function() { return this.says() + ' ' + this.name + ' ' + this.says(); };
var myCat = new Cat('Henrietta'); var says = myCat.says(); var purr = myCat.purr(5); var name = myCat.get_name(); console.log(says); console.log(purr); console.log(name);
Function.method('inherits',function(Parent) { this.prototype = new Parent(); return this; });
var Cat = function(name) { this.name = name; this.saying = 'meow'; }.inherits(Mammal). method('purr', function(n) { var i, s = ''; for(i = 0; i < n; i+=1) { if(s) { s+= '-'; } s += 'r'; } return s; }).method('get_name' function() { return this.says() + ' ' + this.name + ' ' + this.says(); });
var myCat = new Cat('Henrietta'); var says = myCat.says(); var purr = myCat.purr(5); var name = myCat.get_name(); console.log(says); console.log(purr); console.log(name);
//5.3 var myMamml = { name: 'Herb the Mammal', get_name: function() { return this.name; }, says: function() { return this.saying || ''; } };
var myCat = Object.beget(myMammal); myCat.name = 'Henrietta'; myCat.saying = 'meow'; myCat.purr = function(n) { var i, s = ''; for (i=0;i<n;i++ ) { if(s) { s+='-'; } s += 'r'; } return s; };
myCat.get_name = function() { this.says + ' ' + this.name + ' ' + this.says; };
//5.4函数化
var mammal = function (spec) { var that = {}; that.get_name = function() { return spec.name; }; that.says = function() { return spec.saying || ''; }; return that; };
var myMammal = mammal({name:'Herb'});
console.log(myMammal.get_name()); //Herb console.log(myMammal.says()); //(空字符串) console.log(myMammal.name); //undefined
var cat = function(spec) { spec.saying = spec.saying || 'meow'; var that = mammal(spec); that.purr = function(n) { var i, s = ''; for(i=0;i<n;i+=1) { if(s) { s += '-'; } s += 'r'; } return s; }; that.get_name = function() { return that.says() + ' ' + spec.name + ' ' + that.says(); }; return that; };
var myCat = cat({name:'Henrietta'});
console.log(myCat.get_name());//meow Henrietta meow console.log(myCat.says());//meow console.log(myCat.purr(5));//r-r-r-r-r console.log(myCat.saying);//undefined console.log(myCat.name);//undefined
Function.prototype.method = function(name,func) { this.prototype[name]=func; return this; };
Object.method('superior',function(name) { var that = this, method = that[name]; return function() { return method.apply(that,arguments); }; });
var coolcat = function (spec) { var that = cat(spec), super_get_name = that.superior('get_name'); that.get_name = function(n) { return 'like ' + super_get_name() + ' baby'; }; return that; };
var myCoolCat = coolcat({name : 'Bix'}); var name = myCoolCat.get_name();
console.log(name); //like meow Bix meow baby
//5.5部件
var eventuality = function(that) { var registry = {}; that.fire = function(event) { var array, func, handler, i, type = typeof event === 'string' ? event : event.type; if(registry.hasOwnProperty(type)) { array = registry[type]; for(i = 0; i < array.length; i +=1) { handler = array[i];
func = handler.method; if(typeof func === 'string') { func = this[func]; }
func.apply(this, handler.parameters || [event]); } }
return this; };
that.on = function(type , method, parameters) { var handler = { method: method, parameters:parameters };
if(registry.hasOwnProperty(type)) { registry[type].push(handler); } else { registry[type] = [handler]; } return this; }; //eventuality(that); return that; };
//第6章 数组 //6.1数组字面量 var misc = [ 'string',98.6,true,false,null,undefined, ['nested','array'],{object:true},NaN,Infinity ]; console.log(misc[2]); //true console.log(misc[4]); //null console.log(misc[5]); //undefined console.log(misc[6]); //["nested", "array"] console.log(misc[6][0]); //nested console.log(misc[6][1]); //array console.log(misc[6][2]); //undefined console.log(misc[7]); //Object { object=true} console.log(misc[7].object); //true
//6.5混淆的地方 var misc = [ 'string',98.6,true,false,null,undefined, ['nested','array'],{object:true},NaN,Infinity ]; var obj = {a:'1',b:'aaa',c:misc} console.log(misc.constructor) //Array() console.log(obj.constructor) //Object() console.log(typeof misc.constructor) //function
var is_array = function(value) { return value && typeof value === 'object' && //value.constructor === Array;(//此方法不同识别从不同的窗口(window)或帧(frame)里构造的数组) typeof value.length === 'number' && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length')); }; console.log(is_array(misc)); //true console.log(is_array(obj)); //false
//6.6方法 Function.prototype.method = function(name,func) { this.prototype[name]=func; return this; };
Array.method('reduce',function(f,value) { var i; for(i = 0;i <this.length;i++) { value =f(this[i],value); } return value; });
var data = [4,8,15,16,23,42]; var add = function(a,b) { return a + b; };
var mult = function(a,b) { return a*b; };
var sum = data.reduce(add,0); //sum is 108
var product = data.reduce(mult,1); //product is 7418880
data.total = function() { return this.reduce(add,0); };
total = data.total();
console.log(sum); //108 console.log(product); //7418880 console.log(total); //108
//6.7维度 Array.dim = function(dimension,initial) { var a = [],i; for(i=0;i<dimension;i++) { a[i] = initial; } return a; };
var myArray = Array.dim(10,0); console.log(myArray); //[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
var matrix = [ [0,1,2], [3,4,5], [6,7,8] ]; console.log(matrix[2][1]); //7;
//矩阵,二维数组 Array.matrix = function(m,n,initial) { var a,i,j,mat=[]; for(i=0; i<m; i++) { a = []; for(j=0; j<n; j++) { a[j] = initial; } mat[i]=a; } return mat; };
var myMatrix = Array.matrix(4,4,1); console.log(myMatrix[3][3]); //0
//恒等矩阵 Array.identity = function(n) { var i, mat = Array.matrix(n,n,0); for(i=0;i<n;i++) { mat[i][i] = 1; } return mat; }; console.log(myMatrix); myMatrix = Array.identity(4); console.log(myMatrix[3][3]); //1 console.log(myMatrix);
//第7章 正则表达式 //7.1一个例子 var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/; var url = "http://wwww.ora.com:80/goodparts?q#fragment";
var result = parse_url.exec(url); var names = ['url','schema','slash','host','port','path','query','hash']; var blanks = ' '; var i; for(i=0;i<names.length;i++) { console.log(names[i] + ':' + blanks.substring(names[i].length),result[i]); }
//url: http://wwww.ora.com:80/goodparts?q#fragment //schema:http //slash: // //host: wwww.ora.com //port: 80 //path: goodparts //query: q //hash: fragment
var parse_number =/^-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?$/i; var test = function(num) { console.log(parse_number.test(num); }; test('1'); //true test('number'); //false test('98.6'); //true test('132.21.86.100'); //false test('123.45E-67'); //true test('123.45D-67'); //false
//第8章 方法 Function.prototype.method = function(name,func) { this.prototype[name]=func; return this; };
Array.method('push',function() { this.splice.apply(this,[this.length,0].concat(Array.prototype.slice.apply(arguments))); return this.length; });
var a = ['a','b','c']; var b = ['x','y','z']; var c = a.push(b,true); console.log(c); //5 console.log(a); //['a','b','c',['x','y','z'],true] console.log(a[3][0]);//x
var by = function(name) { return function(o,p) { var a, b; if(typeof o === 'object' && typeof p ==='object' && o && p) { a = o[name]; b = p[name]; if(a === b) { return 0; } if(typeof a === typeof b) { return a < b ? -1 : 1; } return typeof a < typeof b ? -1 : 1; } else { throw 'Expected an object when sorting by ' + name; //{ //name : "Eror", //message: 'Expected an object when sorting by ' + name; //} } }; };
var s = [ {first:'Joe',last:'Besser'}, {first:'Moe',last:'Howard'}, {first:'Joe',last:'Derita'}, {first:'Shemp',last:'Howard'}, {first:'Larry',last:'Fine'}, {first:'Curly',last:'Howard'} ]; var m = ['aa','bb','a',4,8,15,16,23,42]; var n = [4,8,15,16,23,42];
s.sort(by('first')); //s.sort(by('first')).sort(by('last')); console.log(s); //
var sortcallback = function(a,b) { if(a ===b) { return 0; } if(typeof a === typeof b) { return a < b ? -1 :1; } return typeof a < typeof b ? -1:1; }; m.sort(sortcallback); n.sort(sortcallback);
console.log(m); // console.log(n); //
var by = function(name,minor) { return function(o,p) { var a, b; if(typeof o === 'object' && typeof p ==='object' && o && p) { a = o[name]; b = p[name]; if(a === b) { return typeof minor === 'function' ? minor(o,p) : 0; } if(typeof a === typeof b) { return a < b ? -1 : 1; } return typeof a < typeof b ? -1 : 1; } else { throw 'Expected an object when sorting by ' + name; //{ //name : "Eror", //message: 'Expected an object when sorting by ' + name; //} } }; };
s.sort(by('last',by('first'))); console.log(s); //
Array.method('splice',function(start,deleteCount) { var max = Math.max, min = Math.min, delta, element, insertCount = max(arguments.length-2,0), k = 0, len = this.length, new_len, result = [], shift_count; start = start || 0; if(start < 0) { start += len; } start = max(min(start,len),0); deleteCount = max(min(typeof deleteCount === 'number' ? deleteCount :len, len-start),0); delta = insertCount - deleteCount; new_len = len + delta; while(k < deleteCount) { element = this[start + k]; if(element !== undefined) { result[k] = element; } k += 1; } shift_count = len - start - deleteCount; if(delta < 0) { k = start + insertCount; while(shift_count) { this[k] = this[k-delta]; k += 1; shift_count -= 1; } this.length = new_len; } else if(delta > 0) { k = 1; while(shift_count) { this[new_len - k] = this[len - k]; k += 1; shift_count -= 1; } } for(k = 0; k < insertCount; k += 1) { this[start + k] = arguments[k + 2]; } return result; });
var a = ['a','b','c']; var r = a.splice(1,1,'ache','bug','c'); // console.log(a); //['a','ache','bug','c']; console.log(r); //['b']
//Function Function.method('bind', function(that) { var method = this, slice = Array.prototype.slice, args = slice.apply(arguments,[1]); console.log(args); return function() { return method.apply(that,args.concat(slice.apply(arguments,[0]))); }; });
var x = function() { return this.value; }.bind({value:666}); console.log(x()); //666
//RegExp String.method('deentityify',function() { var entity = { quot:'"', lt:'<', gt:'>', };
return function() { return this.replace(/&([^&;]+);/g, function(a,b,c,d) { var r = entity[b]; //console.log(a); //a 依次为 < " > //console.log(b); //b 依次为 1t quot gt //console.log(c); //c 依次为 0 4 10 //console.log(d); //d 为stringObj --> <"> return typeof r === 'string' ? r : a; }); } }());
var text = '<html><body bgcolor=linen><p>'+ 'This is <b> bold<\/b>!<\/p><\/body><\/html>';
var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g; var a,i; while((a=tags.exec(text))) { for(i=0;i<a.length;i+=1) { console.log(('//[' + i + '] ' + a[i]).deentityify()); } console.log(); }
//String.match var text = '<html><body bgcolor=linen><p>'+ 'This is <b> bold<\/b>!<\/p><\/body><\/html>';
var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g; var a,i; a = text.match(tags); for(i=0;i<a.length;i+=1) { console.log(('//[' + i + '] ' + a[i]).deentityify()); }
//附录A //A.3 //返回的值如果是一个表达式, 则这个表达式的开始部分必须与return语句在同一行 var x = function() { return { status:true }; } console.log(x()); //undefined
var x = function() { return{ status:true }; } console.log(x()); //Object { status=true}
//A.6 typeof if (my_value && typeof my_value === 'object') { }
//A.9 float var x = 0.1 + 0.2; console.log(x); //0.30000000000000004 console.log(x.toFixed(1)); //0.3
//A.10 NaN function isNumber(value) { return { typeof value === 'number' && isFinite(value); } };
//A.11 伪数组 Array if(my_value && typeof my_value === 'object' && my_value.constructor === Array) {}
//正可靠的判的数组的方法 if (my_value && typeof my_value === 'object' && typeof my_value.length === 'number' && !(my_value.propertyIsEnumerable('length')) { }
//A.14 对象 var i; var word; var text = "This oracle of comfort has so pleased me, " + "That when I am in heaven I shall desire " + "To see what this child does, " + "and praise my Constructor."; var words = text.toLowerCase().split(/[\s,.]+/); var count = {}; for ( i = 0; i < words.length;i +=1) { word = words[i]; if(typeof count[word] === 'number') { count[word] +=1; } else { count[word] = 1; } } console.log(count);
//附录E //E3 JSON var json_parse = function() { // 这是一个能把json文本解析成JavaScript数据结构的函数 // 它是一个简单的递归降序解析器 var at, //当然字符的索引 ch, //当前字符 escape = { '"': '"', '\\': '\\', '/': '/', b: 'b', f: '\f', n: '\n', r: '\r', t: '\t' }, text, error = function(m) { throw{ name: 'SynctaxError', message:m, at: at, text: text } }, next = function(c){ //如果提供了参数c, 那么检查它是否匹配当前字符 if (c && c !== ch) { error("Expected '" + c + "' instead of '" + ch + "'"); } //获取下一个字符,当没有下一个字符时,返回一个空字符串 ch = text.chartAt(at); at += 1; return ch; }, number = function() { //解析一个数字值 var number , string = ''; if (ch === '-') { string = '-'; mext('-'); } while (ch >= '0' && ch <= '9') { string += ch; next(); } if (ch === '.') { string += '.'; while (next() && ch >= '0' && ch <= '9') { string += ch; } } if (ch === 'e' || ch === 'E') { string += ch; next(); if (ch === '-' || ch === '+') { string += ch; next(); } while (ch >= '0' && ch <= '9') { string += ch; next(); } } number = +string; if (isNaN(number)) { error("Bad number"); } else { return number; } }, string = function(){ var hex, i, string = '', uffff; //当解析字符串时,我们必须找到" 和 \ 字符 if(ch === '"') { while (next()) { if (ch === '"') { next(); return string; } else if (ch === '\\') { next(); if (ch === 'u') { uffff = 0; for (i = 0; i < 4; i++) { hex = parseInt(next(),16); if(!isFinite(hex)) { break; } uffff = uffff * 16 + hex; } string += string.fromCharCode(uffff); } else if ( typeof escape[ch] === 'string') { string += escape[ch]; } else { break; } } else { break; } } } error("Bad String"); }, white = function() {//跳过空白 while (ch && ch <= ' ') { next(); } }, word = function() { //true, false, null switch (ch) { case 't': next('t'); next('r'); next('u'); next('e'); return true; case 'f': next('f'); next('a'); next('l'); next('s'); next('e'); return false; next('n'); next('n'); next('u'); next('l'); next('l'); return null; } error("Unexpected '" + ch + "'"); }, value, //值函数的点位符 array = function() { //解析一个数组值 var array = []; if (ch === '[') { next('['); white(); if (ch === ']') { next(']'); return array; //空数组 } while (ch) { array.push(value()); white(); if (ch===']') { next(']'); return array; } next(','); white(); } } error("Bad array"); }, //解析一个对象值 object = function() { var key, object = {}; if (ch === '{') { next('{'); white(); if (ch === '}') { next('}'); return object; //空对象 } while(ch) { key = string(); white(); next(':'); object[key] = value(); white(); if (ch === '}') { next('}'); return object; } next(','); white(); } } error("Bad object"); }, //解析一个JSON值,它可以是对象,数组,字符串,数字或一个词 value = function() { white(); switch (ch) { case '{': return object(); case '[': return array(); case '"': return string(); case '-': return number(); default: return ch >= '0' && ch <= '9' ? number() :word(); } };
//返回json_parse函数,它将能访问上述所有的函数和变量. return function(source,reviver) { var result; text = source; at = 0; ch = ' '; result = value(); white(); if (ch) { error("Syntax error"); } //如果存在reviver函数,我们就递归地对这个新结构调用walk函数, //开始时先创建一个临时的启动对象,并以一个空字符串作为键名保存结果 //然后传递每个"名/值"对给reviver函数去处理可能存在的转换 //如果没有reviver函数,我们就简单地返回这个结果 return typeof reviever === 'function' ? function walk(holder,key) { var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value,k)) { v = walk(value,k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder,key,value); }({'':result},''):result; } }();