JavaScript 语言精粹(中文高清版)- 读书笔记


JavaScript 语言精粹(中文高清版) ——读书笔记(20121212 第一遍) JavaScript 语言精粹(中文高清版) ................................................................................................ 1 第一章节 精华 .................................................................................................................................. 1 第二章节 语法 ................................................................................................................................ 2 第三章节 对象 .................................................................................................................................. 4 第四章节 函数 .................................................................................................................................. 8 第五章节 继承 ................................................................................................................................ 19 第六章节 数组 ................................................................................................................................ 24 第七章节 正则表达式 ..................................................................................................................... 27 附录 A 糟粕 ..................................................................................................................................... 43 附录 B 鸡肋 ..................................................................................................................................... 46 附录 C JSLint .................................................................................................................................... 47 附录 E JSON ..................................................................................................................................... 48 目前已经阅读了的章节:1、2、3、4、附录 A、附录 B、5、10、9、6、7、8 //20121212 阅读完第一遍 理解不清楚的地方: 递归 有几个递归算法没有怎么弄明白 闭包 套用 部件 JSON 解析器 第一章节 精华 1、主要讲述了为什么要使用 javascript,以及本书只介绍 javascript 的精华部份。 2、method 方法去定义新方法 Function.prototype.method = function(name,func){ this.prototype[name] = func; return this; } 第二章节 语法 1、注释 /**/ 块注释 //行注释 注释一定要精确的描述代码,否则”没有用的注释比没有注释更糟糕 块注释对于注释的代码来说是不安全的,如: /* var rm_a = /a*/.match(s); */ 故建议:避免使用块注释(/**/),而使用行注释(//)代替 2、标识符 标识符被用于对象,变量,参数,属性名,运算符,标记 不能使用的关键字 abstract boolean break byte case class char const continue default delete double do debugger else extends enum export false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true typeof try var void volatile while with 以上大部分保留字并未用于这门语言中,以上不包括应该被保留而未被保留的关键字, 如 undefined, NaN, Infinity javascript 不允许使用保留关键字来命名变量和参数,同时 JavaScript 不允许在对象 字面量中,或者在一个属性 表达式的点之后,使用保留字作为对象的属性名。 3、数字 JavaScript 只有一个单一的数字类型,它在内部表示为 64 位的浮点数,和 java 的 Double 一样 1 与 1.0 是相同的值. 有指数部分: 100 和 1e2 是相同的值 值 NaN 是一个数值,它表示不能产生正常结果的运算结果,NaN 不等于任何值,包括它自 己. 可以用函数 isNaN 检测出来. 值 Infinity 表示所有大于 1.79769313486231570e+308 的值 数字拥有方法,如 Math.floor(number)表示将一个数字转换为整数. 4、字符串 字符串可以被包围在单引号('')或双引号("")中,(\)反斜线是转义字符 JavaScript 被创建时 Unicode 是一个 16 位的字符集,所以 JavaScript 的所有字符都是 16 位的。 JavaScript 没有字符类型,要表示一个字符只需要,创建一个只包含一个字符的字符串 即可。 字符串是不可变的,一旦被创建就不可改变。 字符串属性和方法 如,'cat'.length == 3 'cat'.toUpperCase() === 'CAT' (===)恒等运算符 5、语句 代码块是一对花括号({})中的一组语句,不像许多其它语言, JavaScript 中的代码块不会创建新的作用域 因此变量的定义应该放在代码块的顶端而不是代码块中。 被当作假的值 false null undefined 数字 0 数字 NaN 空字符串' ' if, switch, while, for, for in, do while, try catch, throw 6、表达式、字面量、数组 函数 第三章节 对象 1、JavaScript 的简单类型包括数字、字符串、布尔值(true,false)、null 值、undefined 值 其它所有的值都是对象。 对象字面量提供了一种非常方便的创建新对象值的表示方法。 一个对象字面量就是包含在一对花括号中的零个或多个“名/值”对 如, var empty_object = {}; var stooge = { "firstName":"lin", "lastName":"He" } 2、检索 检索对象中的值,优先考虑使用(.)表示法来获取,因为它更紧凑 stooge["firstName"] //lin stooge.firstName //lin 不存在的属性 stooge.son //undefined stooge.son.firstName //throw TypeError 3、更新 对象中的值可以通过赋值语句来更新,如 stooge.firstName = "LINLIN" 如果之前没有该属性名,则就会将该属性扩充到该对象中去 stooge.age = 23 stooge.son ={ "firstName":"small son", "lastName":"son" }; 4、引用 对象通过引用来传递,所以它永远也不会被拷贝 var x = stooge.firstName; //LIN x.firstName = "LIN1"; var y = stooge.firstName; //因为 x、stooge 都是指向同一个对象的引用,所以 y 等于 LIN1 var a ={},b={}, c={}; //a、b、c 每个都引用了一个不同的空对象 var a = b = c ={}; //a、b、c 都引用了同一个空对象 5、原型 每个对象都链接到一个原型对象,并且可以从中继承属性。 所以通过对象字面量创建的对象都连接到 Object.prototype 这个 JavaScript 中标准 的对象。 当你创建一个新对象时,可以选择某个对象作为它的原型。JavaScript 提供的机制杂乱 而复杂,但可以明显的被简化, 此处给 Object 对象增加一个 beget 方法。这个 beget 方法创建一个使用原对象作为其 原型的新对象 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.firstName = "new Name"; 而 stooge.firstName //还是 Lin 原型链接只有在检索值的时候才用到 委托 尝试去获取对象的某个属性值时,如果该对象没有此属性,则 JavaScript 会试着从原型 对象中去获取属性值, 如果原型对象也没有该属性,则再从原型的原型中去寻找。。。。直到 Object.prototype 为终点 如果属性完全不在原型链接中,则值为 undefined,这个过程称为委托。 原型关系是一种动态关系。 即,如果添加一个属性到原型对象中,该属性会对基于该原型对象所创建的对象可见。 6、反射 typeof 对确定对象的属性类型很有帮助 typeof flight.number //number typeof flight.status //string typeof flight.arrival //object typeof flight.manifest //undefined 注意原型链中的属性也会产生一个值,如 typeof flight.toString() //function typeof flight.constructor() //function 有两个方法可以剔除掉这些不需要的值,一个是让自己的程序去检查剔除函数值 另一个方法是 hasOwnProperty 方法,如果对象拥有独立的属性则返回 true,否则返回 false hasOwnProperty 不会检查原型链 flight.hasOwnProperty("number") //true flight.hasOwnProperty("constructor") //flase 7、枚举 for in 属性名出现的顺序是不确定的。 var name; for(name in another_stooge){ if(typeof another_stooge[name] != 'function'){ document.writeln(""+name +":"+ another_stooge[name]); } } 8、删除 delete 可以用来删除对象的属性,它不会触及原型中的属性。 删除对象中的属性,可能会让来自原型链接中的属性浮现出来 delete another_stooge.age another_stooge.age //可能会等于 stooge.age ******************* 9、减少全局变量的污染 JavaScript 可以很容易的定义保存所有应用资源的全局变量,但全局变量削弱了程序的 灵活性,故 应该尽量避免。 最小化使用全局变量的方法是,在你的应用中只创建一个全局变量。如 var MYAPP = {}; MYAPP.stooge = { "firstName":"Joe", "lastName": "Howard" }; MYAPP.flight = { airline:"Oceanic", number:815, departure:{ IATA:"SYD", time:"2004", city:"sydeny" }, arrival:{ IATA:"LAX", time:"2004-09-23" city:"Los An } }; 另一种减少全局污染的方法。 使用闭包, ===================20121202 阅读至第 3 章节============ 第四章节 函数 1、函数对象 JavaScript 中的函数就是对象,函数对象的原型 Function.prototype (该原型对象本 身链接到 Object.prototype) 如果没有给函数命名,它会被认为是匿名函数 var add = function(a,b){ return a+b; } 函数可以通过函数字面量来创建,函数字面量包括四个部份: 1)、保留关键字 function 2)、函数名 3)、参数 4)、{} 函数字面量可以定义在任何允许出现表达式的地方。函数可以被定义在函数中。 通过函数字面量创建的函数对象包含一个连接到外部上下文的连接,这被称为闭包。这 是 JavaScript 强大表现力的根基。 2、调用 调用函数将暂停当前函数的执行,传递控制权和参数给新函数,除了声明时定义的参数 外,还附加两个参数:this 和 arguments this 在面向对象编程中非常重要,this 的值取决于调用的模式 JavaScript 中一共有四种调用模式。 1)、方法调用模式 2)、函数调用模式 3)、构造器调用模式 4)、apply 调用模式 调用函数时,参数值不会进行类型检查。 参数值多了,多余的将被忽略,参数值少了,缺失的参数将被定义为 undefined 方法调用模式 当一个函数被保存为对象的一个属性时,我们称它为方法。 如果一个存取表达式包含一个属性存取表达式(即一个.表达式或[subscript]下标表达 式),那么它被当作一个方法来调用。 例 var myObject = { value: 0, increment:function(inc){ this.value += typeof inc === 'number' ? inc : 1; } }; myObject.increment(); document.writeln(myObject.value); myObject.increment(2); document.writeln(myObject.value); 方法可以用 this 去访问对象,所以它能从对象中取值或修改对象。this 到对象的绑定 发生在调用时,通过 this 取得它们所属对象上下文的 方法称为公共方法。 ******************** 函数调用模式 var sum = add(3,4); //sum 的值为 7 当函数以函数调用模式调用时,this 被绑定到全局对象。这是语言设计上的一个错误? 倘若语言设计正确, 当内部函数调用时,this 应该被绑定到外部函数的 this 变量。这个设计错误的后果是 方法不能利用内部函数来帮助它完成工作,因为内部 函数的 this 被绑定了错误的值,所以不能共享该方法对对象的访问权 解决方案: 为该方法定义一个变量(按照约定,定义为 that),并给它赋值为 this,内部函数 就可以通过那个变量来访问到 this。 myObject.double = function(){ var that = this; //解决方法 var helper = function(){ that.value = add(that.value,that.value); }; helper();//以函数的形式调用 helper }; myObject.double();//以方法的形式调用 double document.writeln(myObject.getValue()); 构造器调用模式 JavaScript 是一门基于原型继承的语言。对象可以直接从其它对象继承属性。 //创建一个 Quo 的构造器函数,它构造一个带 status 属性的对象。 var Quo = function(str){ this.status = str; }; //给 Quo 的所有实例提供一个 getStatus 方法。 var Quo.prototype.getStatus = function(){ return this.status; } //构造一个实例 var myQuo = new Quo("confused"); document.writeln(myQuo.getStatus()); 目的就是结合 new 前缀调用的函数被称为构造器函数。按约定,它们保存在以大写格式 命名的变量里。 如果调用构造器函数没有在前面加上 new,可能会发生非常糟糕的事情,没有编译时的 警告,也没有运行时的警告。 不推荐使用这种形式的构造器函数。 Apply 调用模式 JavaScript 是一门函数式的面向对象的编程语言,所以函数可以拥有方法。 apply 方法让我们构建一个参数数组,并用其去调用函数,它允许我们选择 this 的值, apply 方法接收两个参数,第一个是 this 的值 第二个是参数数组 //构造一个包含两个数字的数组并让其相加 var array = [3,4]; var add = function(a,b){ return a + b ; }; var sum = add.apply(null,array); document.writeln(sum); //构造一个包含 status 成员的对象, var statusObject = { status:"A-OK" }; //statusObject 并没有继承 Quo.prototype,但我们可以在 statusObject 上调用 getStatus 方法 //尽管 statusObject 并没有一个 getStatus 方法 var status = Quo.prototype.getStatus.apply(statusObject); document.writeln(status); 3、参数 函数被定义时,会得到一个额外的参数,arguments 数组,通过它,函数可以访问所有 它被调用时的参数列表, 包括那些没有被分配给函数定义时形式参数的多余参数,这使得编写一个无须指定参数 的函数成为可能。 //构造一个将很多个值相加的函数, //注意内部定义的变量 sum 并不会与函数外部定义的 sum 产生冲突。 var sum = function(){ var i,sum = 0; for(i=0;i < arguments.length;i++){ sum = sum + arguments[i]; } return sum; }; var sum1 = sum(1,2,3,4,5,6,7,8,9); document.writeln(sum1); 这并不是一个特别有用的模式,第六章中,将会看到如何给数组添加一个相似的方法来 达到同样的效果。 因为语言设计上的一个错误? arguments 并 不 是 一 个 真 正 的 数 组 ,它 只 有 一 个 "array-like"的对象,arguments 拥有一个 length 属性,但它缺少所有 数组的方法。 4、返回 一个函数总会有返回值,如果没有指定返回值,则返回 undefined 如果函数在前面加上一个 new 前缀来调用,且返回值不是一个对象,则返回 this(该新 对象) 5、异常 此例,注释部分报错 var add = function(a,b){ if(typeof a !== 'number' || typeof b !=='number'){ throw{ name:'TypeError', message:'add Needs Number' }; } return a+b; }; var try_it = function(){ try{ add("aaa"); }catch(e){ document.writeln(e.name+":"+e.message); } }; try_it(); 6、给类型添加方法 JavaScript 允许给语言的基本类型添加方法。 给 Object.prototype 添加方法来使得该方法对所有对象可用,这样的方式对函数,数 组,字符串,数字,正则表达式,和布尔值同样适用。 例, 通过给 Function.prototype 增加方法来使得该方法对所有函数可用 Function.prototype.method = function(name,func){ this.prototype[name] = func; return this; }; 通过给 Function.prototype 增加一个 method 方法,我们就不用键入 prototype 这个属 性名了。 JavaScript 没有单独的整数类型,有时候只提取数字中的整数部分是必要的。 通过给 Number.prototype 增加一个 integer 方法来改善它,它会根据数字的正负来判 断使用 Math.ceiling 还是 Math.floor Number.method('integer',function(){ return Math[ this < 0 ? 'ceil' : 'floor'](this); }); document.writeln((23/3).integer()); //-3 Math.ceil() //将小数部分一律向整数部分进位。 Math.floor() //一律舍去,仅保留整数。 Math.round() //四舍五入 JavaScript 去掉前后空白字符 String.method('trim',function(){ return this.replace(/^(\s*)|(\s*)$/g,""); }); **************** 基本类型是公共结构,所以在类库混用时得小心 //有条件的增加一个方法 Function.prototype.method = function(name,func){ if(!this.prototype[name]){ this.prototype[name] = func; } return this; }; for in 语句在原型继承时表现糟糕 7、递归 ****** 有几个递归算法没怎么明白 一些语言提供了尾递归优化,如果一个函数调用自身递归调用的结果,那么调用过程会 被替换成一个循环。 JavaScript 当前并没有提供尾递归优化 8、作用域 大多数语言提供块级作用域({}) JavaScript 不支持块级作用域 JavaScript 支持函数作用域 定义在函数中的参数和变量在函数外部是不可以见的 ******************没怎么弄明白***************************** 9、闭包 var myObject = function(){ var value = 0 ; return { increment:function(inc){ value += typeof inc === 'number' inc : 1; }, getValue:function(){ return value; } }; }(); //创建一个名为 quo 的构造器函数 var quo = function(status){ return { getStatus:function(){ return status; } }; }; 注: 函数可以访问它被创建时的上下文环境,这被称为闭包,如上例 //构造一个 quo 实例 var myQuo = quo("sss"); document.writeln(myQuo.getStatus()); //没反应? var fade = function(node){ var level = 1; var step = function(){ var hex = level.toString(16); node.style.backgroundColor = '#FFFF'+ hex + hex; if(level < 15){ level +=1; setTimeout(step,100); } }; setTimeout(step,100); }; fade(document.body); 理解内部函数可以访问外部函数的实际变量而无须复制是很重要的 //糟糕的例子 var add_handlers = function(nodes){ var i; for(i = 0 ;i< nodes.length; i++){ nodes[i].onclick = function(i){ alert(e); } } }; //结束糟糕的例子 var add_handlers = function(nodes){ var i; for(i = 0 ;i< nodes.length; i++){ nodes[i].onclick = function(i){ return function(e){ alert(e); } }(i); } }; 11、模块 可以通过函数和闭包来构造模块 模块是一个提供接口却隐藏状态与实现的函数或对象 String.method('deentityify',function(){ //字符实体表 var entity = { quot:'"', lt:'<', gt:'>' }; //返回 deentityify 方法 return function(){ return this.replace(/&([/^&;]+);/g, function(a,b){ var r = entity(b); return typeof r == 'string'? r : b; } ); }; }()); document.writeln("<">abc".deentityify()); 模块模式的一般形式: 1)、一个定义了私有变量和函数的函数 2)、利用闭包创建可访问私有变量和函数的特权函数 3)、最后返回这个特权函数,或者把它保存到一个可访问的地方 模块模式的通常结合单例模式使用。 JavaScript 中的单例就是用对象字面量表示法创建对象,对象的属性值可以是数值或函 数并且属性值在该对象的生命周期中不会发生变化。 通常作为工具为程序其他部份提供支持。 var serial_maker = function(){ var prefix = ''; var seq = 0; return { set_prefix:function(p){ prefix = String(p); }, set_seq:function(s){ seq = s; }, gensym:function(){ var result = prefix + seq ; seq +=1; return result; } }; }; var seqer = serial_maker(); seqer.set_prefix("H"); seqer.set_seq(10000); var unque = seqer.gensym(); 12、级联 有一些函数没有返回值。 如果我们让这些函数返回 this 而不是返回 undefined,就可以启用级联。 如 getElement("divId"). move(350,200). width(300). height(400); **********没理解 13、套用 套用允许我们将函数与传递给它的参数相结合去产生出一个新的函数 14、记忆 函数可以用对象去记住先前操作的结果,从而避免无谓的运算。 var fibonacci = function(n){ return n < 2? 1:fibonacci( n - 1) + fibonacci( n- 2); }; for(var i = 0; i < 11;i++){ document.writeln(fibonacci(i)); } fibonacci 函数被调用了 453 次,我们调用了 11 次,自身调用了 442 次 var fibonacci = function(n){ var memo = [0,1]; var fib = function(n){ var result = memo[n]; if(typeof result !== 'number'){ result = fib(n-1) + fib(n-2); memo[n] = result; } return result; }; return fib; }(); 这个函数调用了 29 次,我们调用了 11 次,自身调用了 18 次。 可设计上面这种函数的一般形式: var memoizer = function(memo,fundamental){ var shell = function(n){ var result = memo[n]; if(typeof result !== 'number'){ result = fundamental(shell,n); memo[n] = result; } return result; }; return shell(); }; 现在可以通过 memoizer 来定义 fibonacci 函数 var fibonacci = memoizer([0,1],function(shell,n){ return shell(n-1) + shell(n-2); }); 产生一个可记忆的阶乘函数 var factorial = memoizer([1,1],function(shell,n){ return n * shell(n - 1); }); ===================20121206 阅读完第 4 章节============ 第五章节 继承 1、伪类 “伪类” 可以给不熟悉 JavaScript 的程序员带来便利,但它隐藏了该语言的真实本质。 在基于类的语言中,类的继承是代码重用的唯一方式(?),JavaScript 有着更多更好 的选择。 2、对象说明符 有时候构造器要接收一大堆参数,要记住参数的顺序可能非常困难,故在构建对象构造 器时可让其接收一个简单的对象说明符 如 //不推荐 var myObject = maker(f,l,s,c); //推荐写法 var myObject = maker({ first:f, last:l, state:s, city:c }); 3、原型 在一个纯粹的原型模式中,我们会摒弃类,转而关注对象。 基于原型的继承相比基于类的继承在概念上更为简单:一个新对象可以继承一个旧对象 if(typeof Object.beget !== 'function'){ Object.beget = function(o){ var F = function(){}; F.prototype = o; return new F(); }; } var myMammal = { name:'herb the Mammal', get_name:function(){ return this.name; }, says:function(){ return this.saying || ''; } }; var myCat = Object.beget(myMammal); myCat.name = 'xiaoMao'; myCat.saying = 'meow'; myCat.purr = function(n){ var s = ''; for(var i=0;i < n;i++){ if(s){ s += '-'; } s += 'r'; } return s; }; myCat.get_name =function(){ return this.says + ' ' + this.name + ' ' + this.says; }; 这是一种“差异化继承”。通过定制一个新的对象,指明了它与所基于的基本对象的区别。 4、函数化 隐藏对象的私有属性 模块模式的应用: 构造一个产生对象的函数开始,该函数包括如下步骤 1)、它创建一个对象 2)、它选择性的定义私有变量和方法。这些就是通过 var 语句定义的普通变量 3)、它给这个新对象扩充方法,那些方法将有特权去访问参数,以及在第二步中通过 var 语句定义的变量 4)、它返回那个新对象 函数构造器的伪代码模板 var constructer = function(spec,my){ var that,其它的私有实例变量; my = my || {}; 把共享的变量和函数添加到 my 中 that = 一个新对象 添加 that 的特权方法 return that; }; 将此模式应用到 mammal 中 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'}); 在伪类模式中,构造器函数不得不重复构造器 Mammal 已经完成的工作,在函数化模式中 就不用了,因为构造器 Cat 将会调用构造器 mammal, 让 mammal 去做对象创建的大部份工作 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++){ if(s){ s = s + '-'; } s = s + 'r'; } return s; }; that.get_name = function(){ return that.says() + ' ' + spec.name + ' ' + that.says(); }; return that; }; var myCat = cat({name:'xiaoMao'}); 函数化模式提供了一个处理父类的方法 Object.prototype.method = function(name,func){ if(!this.prototype[name]){ 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'}); 一个持久性对象不会被损害,访问一个持久性对象时,除非被方法授权,否则攻击者无 法访问对象的内部状态。 *********************没怎么懂******* 5、部件 例 构造一个能添加简单事件处理特性到任何对象上的函数。 var eventuality = function(that){ var registry ={}; that.fire = function(event){ //在一个对象上触发一个事件,该事件可以是包含一个事件名称的字符串 //或者是一个拥有事件名称的 type 属性对象 //通过'on'方法注册事件处理程序中匹配事件名称的函数被调用 var array,func,handler,i, type = typeof event ==='string' ? event:event.type; //如果这个事件存在一组事件处理程序,那么就遍历它们按顺序依次执行 if(registry.hasOwnProperty(type)){ for(i=0;i"+s[i].first+":"+s[i].last); } s.sort(by('first')); document.writeln("
========================"); for(var i =0;i"+s[i].first+":"+s[i].last); } sort 方法是不稳定的 第二属性名次要排序 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{ name:'Error', message:'Expected an object when sorting ty ' + name }; } }; }; 9)、array.splice(start,deleteCount,item...) 从 array 中移除 1 个或多个元素,并用新的元素替换。 它返回一个包含被移除元素的数组 var m = ['a','b','c']; m.splice(1,1,'bbb','ccc'); //m 为['a','bbb','ccc','c']; //r 为['b']; splice 方法可以像这样实现 Array.method('mysplice',function(start,deleteCount){ var max = Math.max; var min = Math.min; var insertCount = max(arguments.length - 2,0); var len = this.length; var result = []; var k = 0; var new_len,shift_count,delta,element; start = start || 0; if(start < 0){ start = start + len; } 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 = k + 1; } shift_count = len - start - deleteCount; if(delta < 0){ k = start + insertCount; while(shift_count > 0){ this[k] = this[k- delta]; k = k + 1; shift_count = shift_count - 1; } this.length =new_len; }else if(delta > 0){ k = 1; while(shift_count > 0){ this[new_len - 1] = this[len - 1]; k = k + 1; shift_count = shift_count - 1; } } for(k =0;k < insertCount;k++){ this[start + k]= arguments[k+2]; } return result; }); var m = ['a','b','c','d']; var n = m.mysplice(1,2,'bbb','ccc','cc'); alert(m); alert(n); 10)、array.unshift(item...) 像 push 方法一样将元素添加到数组中,但是它是添加到数组的开始部份 它返回 array 的新长度值 var m = ['a','b','c']; var n = m.unshift('aaa','bbb'); 注意:IE6 之前 JScript 引擎对 unshift 方法的实现有错误,它的返回值永远都是 undefined,IE7 修复了此 BUG unshift 方法可以像这样实现: //此处有错误,不能运行 Array.method('myUnshift',function(){ this.splice.apply(this,[0,0].concat(Array.prototype.slice.apply(arguments))) ; reurn this.length; }); 2、Function function.apply(thisArg,argArray) apply 方法调用函数 function,传递一个将被绑定到 this 上的对象和一个可选的参 数数组,apply 方法被用在 apply 调用模式上 Function.method('bind',function(that){ var method = this; var slice = Array.prototype.slice; var args= slice.apply(arguments,[1]); return function(){ return method.apply(that,args.concat(slice.apply(arguments,[0]))); }; }); var x = function(){ return this.value; }.bind({value:123}); alert(x()); 3、Number 1)、number.toExponential(fractionDigits) toExponential 方 法 把 这 个 Number 转换成指数形式的字符串,可选参数 fractionDigits 控制小数点后的位置,它的值必须是在 0-20 之间。 2)、number.toFixed(fracgtionDigits) toFixed 将 number 转换成 10 进制形式的字符串,可选参数 fractionDigits 控制小 数点后数字的位数,0-20 之间,默认为 0 3)、number.toPrecision(precision) toPrecision 方法将 number 转换成十进制形式的字符串, precision 控制有有效 数字的位数,值在 0-21 之间 4)、number.toString(radix) 把这个 number 转换成一个字符串,可选参数 radix 控制基数,值在 2-36 之间,默 认为 10 例,alert(Math.PI.toString(2)); 4、Ojbect object.hasOwnProperty(name) object 包含一个名为 name 的属性返回 true,否则返回 false 原型链中的同名属性不会被检查 5、RegExp 1)、regexp.exec(string) exec 方法是正则表达式最强大(和最慢)的方法 如果成功的匹配 regexp 和 string,它将返回一个数组。下标 0 是正匹配的字符串, 下标 1,2。。。捕获的分组 匹配失败返回 null 如果 regexp 带有一个 g 标志,那它匹配是从 regexp.lastIndex(初始值为 0)开始 的,匹配成功 regexp.lastIndex 将被设置为匹配字符串后的第一个字符,匹配失败则被重置为 0 2)、regexp.test(string) regexp.test 方法是正则表达式最简单(和最快)的方法 如果匹配成功返回 true,否则返回 false。不要对这个方法使用 g 标志 test 方法可以像这样实现 RegExp.method('myTest',function(string){ return this.exec(string) !== null; }); 6、String 1)、string.charAt(pos) charAt 方法返回在 string 中在 pos 位置处的字符,pos 小于 0 或者大于 string 的 长度,将返回空字符串 JavaScript 没有字符类型,所以返回结果为一个字符串 charAt 可以像这样实现 String.method('myCharAt',function(){ return this.slice(0,1); }); 2)、string.charCodeAt(pos) charCodeAt 方法同 charAt 一样,它返回的是以整数形式表示 string 在 pos 位置处 的字符的码值 pos 小于 0 或者大于 string.length,返回 NaN var m ='ACury'; var n = m.charCodeAt(0); 3)、string.concat(item...) 通过将其它的字符串连接在一起构造一个新的字符串, var c ='A'; c.concat('b','c'); //c 的值为 'Abc' 4)、string.indexOf(serachString,position) 返回要查找字符串在该字符串中的位置,若找到返回第一个匹配字符的位置,否则 返回-1 可选参数可以设置从 position 位置开始查找 var text = "Mississippi"; var p = text.indexOf('ss'); //2 var p = text.indexOf('ss',3); //5 var p = text.indexOf('ss',6); //-1 5)、string.lastIndexOf(serachString,position) 该方法和 indexOf 类似,只不过它是从 string 的尾部开始查找 var text = "Mississippi"; var p = text.lastIndexOf('ss'); //5 var p = text.lastIndexOf('ss',3); //2 var p = text.lastIndexOf('ss',6); //5 6)、string.localCompare(that) 比较两个字符串,如果 string 比 that 小返回负数,相等返回 0 7)、string.match(regexp) match 方法匹配一个字符串和正则表达式 如果没有 g 标识,效果同 regexp.exec(string) 如果有 g 标识,它返回一个除捕获分组之外的所有匹配的数组 8)、string.replace(searchValue,replaceValue) replace 方法对 string 进行查找和替换操作,并返回一个新的字符串。参数可以是 一个字符串或者正则表达式。 如果是字符串,它只会替换第一次出来的地方 如果是正则表达式,并带有 g 标志,则会替换所有匹配之处 如果没有带 g 标志,也只替换第一处 replaceValue 可以是一个字符串或函数,若为字符串,$有特殊的含义 var oldareacode = "(555)666-2222"; var newAreaCode = oldareacode.replace(/\((\d{3})\)/g,"$1-"); //oldareacode 为 "(555)666-2222"; //newAreaCode 为 "555-666-2222"; 美元符号序列 替换对象 $$ $ $number 分组捕获的文本 $& 整个匹配的文本 $` 匹配之前的文本 $' 匹配之后的文本 如果 replaceValue 是一个函数,此方法将对每个匹配调用它,并且该函数返回的字 符串将被用作替换文本。 Object.prototype.method = function (name,func){ this.prototype[name] = func; return this; }; String.method('entitify',function(){ var character = { '<':'<', '>':'>', '&':'&', '"':'"' }; return function(){ return this.replace(/[<>&"]/g,function(c){ return character[c]; }); }; }()); alert("<>&\"".entitify()); 9)、string.search(regexp) 和 indexOf 方法类似,但它只接收正则表达式作为参数,而不是一个字符串。如果 找到匹配返回匹配的第一个字符 的位置,否则返回-1,此方法会忽略 g 标志 10)、string.slice(start,end) slice 方法是复制 string 的一部分来构造一个新的字符串,如果 start 为负数它将 与 string.length 相加 end 参数可选,默认为 string.length,如果 end 为负数,它将与 string.length 相 加 若 end < start 返回空字符串 11)、string.split(separator,limit) split 方法把 string 分割成片段来创建一个字符串数组。可选参数可以限制被分割 片段的数量 separator 参数可以是一个字符串或正则表达式 当其为空字符串里,将返回单字符数组 var digits = "0123456789"; var a = digits.split("",5); //a 为 ['0','1','2','3','4'] var digits = "|a|b|c|d|"; var a = digits.split("|"); //a 为 ['','a','b','c','d',''] var text = "last, first , middle"; var a = text.split(/\s*,\s*/); //\s 表示 unicode 空白符(不完全) //a 为 ['last','first','middle'] 特例 来自分组捕获的文本将会被包含在被分割后的数组中 var text = "last, first , middle"; var a = text.split(/\s*(,)\s*/); //a 为,['last',',','first',',','middle'] 当 sparator 是一个正则表达式里,有一些 JavaScript 的实现会在输出数组中禁止 空字符串 var digits = "|a|b|c|d|"; var a = digits.split(/\|/); //一些系统中 a 为 ['','a','b','c','d',''] (本机测试,FireFox 为这种情况) //另外一些系统中 a 为['a','b','c','d'] (本机测试,IE8 为这种情况) 12)、string.substring(start,end) substring 方法的用法同 slice,但它不能处理负数参数,没有理由使用它,请用 slice 代替。 13)、string.toLocaleLowerCase() string.toLocaleLowerCase 方法返回一个新字符串,使用本地化规则把这个字符串 中的所有字母都被转换为小写格式 此方法主要用在土耳其语上,因为土耳其语中的“I”转换为“l”,而不是“i” 14)、string.toLocaleUpperCase() string.toLocaleUpperCase 方法返回一个新字符串,使用本地化规则把这个字符串 中的所有字母都被转换为大写格式 此方法主要用在土耳其语上,因为土耳其语中的“i”转换为“I”,而不是“I” 15)、string.toLowerCase() string.toLowerCase 方法返回一个新字符串,这个字符串中的所有字母都被转换为 小写格式 16)、string.toUpperCase() string.toUpperCase 方法返回一个新字符串,这个字符串中的所有字母都被转换为 大写格式 17)、String.fromCharCode(char...) String.fromCharCode 函数从一串数字中返回一个字符串 var a = String.fromCharCode(65,97,116); //a 的值为 "Aat" ===========================20121212 阅读完第 8 章节================= 第九章节 代码风格 注意代码风格,我自认为自己在此方面还是不错的。 第十章节 优美的特性 只是简单的描述 JavaScript 有哪些优美特性,其实在上面章节已经介绍了。 如 函数是头等对象 基于原型继承的动态对象 对象字面量和数组字面量 ===========================20121207 阅读完第 9、10 章节================= 附录 A 糟粕 1、全局变量 共有三种方式定义全局变量: var foo = value; //第 1 种 window.foo = value; //第 2 种 foo = value; //第 3 种是直接使用未定义的变量 2、作用域 JavaScript 没有块级作用域({}) 3、自动插入分号 JavaScript 有一个机制,它试图通过自动插入分号来修正有缺损的程序。它可能会掩盖 更为严重的错误 有时它会不合时宜的插入一个分(;)号 如 return { status:true }; 看起来会返回一个包含 status 成员的对象,但是自动插入分号让它变成返回 undefined 如何避免,应该改写为: return { status:true }; 4、保留字 abstract boolean break byte case class char const continue default delete double do debugger else extends enum export false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true typeof try var void volatile while with 这些单词的大多数没有在语言中使用 我们不能用它来命名变量或者参数 var method; //正确 var class; //非法 var object ={box:value}; //正确 var object ={case:value}; //非法 var object ={'case':value}; //正确 object.box = value; //正确 object.case = value; //非法 object['case'] = value; //正确 5、Unicode 当设计 JavaScript 的时候,Unicode 预计最多会有 65536 个字符,而从那以后容量增长 到了拥有一百万个字符 JavaScript 的字符是 16 位的,足够覆盖原有的 65536 个字符的,剩下的一百万字符都 是用一对字符来表示的 Unicode 把一对字符认为是一个单一的字符,而 JavaScript 认为一对字符是两个不同的 字符 6、typeof typeof 运算符返回一个用于识别其运算数类型的字符串 typeof 99.9 返回 'number' 不幸的是, typeof null 返回 'object' 而不是'null' 更好的检测 null 的方法 my_value === null typeof 不能识别对象与 null, 检测对象的方法 if(my_object && typeof my_object === 'object'){ //先排除 null,my_object 是一个对象或者数组 } 对正则表达式的类型识别 typeof /a/ 返回 'function' 7、parseInt parseInt 是一个将字符串转换为整数的函数,它遇到非数字时停止解析。 所以,parseInt("15") 与 parseInt("15 adss"); 值都是 15 如果字符串第一个字符是"0",那字符串将被基于 8 进制而不是十进制来求值 parseInt("08") 与 parseInt("09") 都是 0 解决方法: parseInt("08",10); 结果就是 8 建议问题提供这个基数参数。 8、+ 如果想用 + 去做加法运算,请确认两个运算数都是数字 9、浮点数 二进制的浮点数不能正确处理十进制的小数 故 0.1 + 0.2 不等于 0.3 这是 JavaScript 经常被报告的 bug 浮点数的整数运算是精确的 解决方法 美元可以*100 改为美分来解决,最后在除以 100 换成美元 10、NaN typeof NaN == 'number' //true NaN 不等于 NaN JavaScript 提供了一个函数 isNaN 用于识别数字与 NaN 判断是一个数值是否可以用作数字的最佳使用方法是 isFinite 函数 它会筛除掉 NaN 与 Infinity,不幸的是,isFinite 会试图将它的运算数转换为一个数字, 如果值不是一个数字,它就不是一个好的测试 故编写自己的判断数字的函数 function isNumber(value){ return typeof value === 'number' && isFinite(value); } 11、伪数组 JavaScript 中没有真正的数组,不用给数组设置维度,永远也不会越界,但是性能相比 真正的数组可能相当糟糕 12、假值 0 NaN '' false null undefined NaN 与 undefined 并不是常量,是全局变量,可以改变它们的值(千万别这么做) 13、hasOwnProperty hasOwnProperty 方法可以被用作过滤器避开 for in 语句的一个问题 不幸的是,hasOwnProperty 是一个方法,不是一个运算数,可以被替换 如 var name; var stooge.hasOwnProperty = null; //地雷 for(name in stooge){ if(stooge.hasOwnProperty(name){ //触雷 document.writeln(stooge[name]); } } 14、对象 JavaScript 永远不会真的有空对象,因为它们可以从原型链中取得成员元素 附录 B 鸡肋 1、== 2、with 3、eval 4、continue 5、switch 贯穿 6、缺少块的语句 if , while,do ,for 可以接受一个括在花括号里面的代码块,与可以接受单行语句 单行语句带来的好处可以节约两个字节,却模糊了程序的结构 7、++ -- 8、位运算符 9、function 对比函数表达式 理解函数既是数值很重要 一个语句不能以一个函数表达式开头,解决方法把函数表达式放在一个圆括号中 (function(){ var hidden_variable; //这个函数可能对环境有一些影响,但不会引入新的全局变量 })(); 10、类型包装对象 JavaScript 有一套类型包装对象 new Boolean(false) 会返回一个对象,该对象有一个 valueOf 方法返回被包装的值, 故 不要使用 new Boolean 、 new String 、 new Number 避免使用 new Object 与 new Array ,用{}与[]代替 11、new 如果忘记使用此 new 运算符,所得到的就是一个普通的函数调用,并且 this 被绑定到全 局对象,而不是新创建的对象。 意味着当你的函数尝试去初始化新成员元素时它将会污染全局变量。 更好的策略是根本不去使用 new 12、void 很多语言中,void 是一种类型,表示没有值 JavaScript中void是一个运算符,接收一个运算数并返回undefined,应该避免作用它。 附录 C JSLint 是 JavaScript 的一个代码辅助工具,取得 js 源文本进行扫描。分析可能问题。 附录 E JSON 服务器端发回的 JSON 格式字符串解析 var myData = eval('('+ myJSONText + ')'); 因为 eval 函数存在安全问题,故可用 JSON.parse 替代 eval 如果文本 str 中包含任何危险数据,那么 JSON.parse 将抛出异常 ***************************** 一个 JSON 解析器 还未阅读。。。。 ===================20121206 阅读了附录 A 与附录 B=========
还剩47页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

java_hl

贡献于2013-04-28

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf