每次去图书馆都能随手带两本不错的书回来。看了不少书。有不少收益。慢慢总结笔记。发现一次看很多本书,更容易理解书里的概念。
第一章
基本概念:
模式: 重现事件或对象的主题……是一个可用来产生其他事物的模板或模型。
好处:1.经验总结。2.某种程度上的抽象。3.改善交流。共同语言。
设计模式。 编码模式:提供关于该语言很好的独特的体验。 反模式。
第二章、基本技巧
编写可维护的代码
维护自己写的代码的问题:花时间重新学习和理解问题。花时间理解当时用于解决相应问题的代码。
如何叫可维护:阅读性、一致性、预见性、看起来如同一个人编写、有文档。
全局变量
问题:不好管理。容易跟别人或自己的代码冲突导致功能失调。
意外生成:
1.函数中的隐式声明。有时候不小心就省略了var。
2.函数中 var a = b = 0 ; b是全局变量。
3. 有时候 的 this.a = 1;这种也会变成全局变量。
var全局变量不能delete。 隐式的可以。
全局对象 在非浏览器下可能不叫 window 。 var globe = (function(){ return this;})();
如何减少全局变量:
1.单一var模式。 dom可以用局部变量表达起来。
2.即时函数。(作用域沙箱)。
3.命名空间模式。
for循环的优化
html容器是dom方法返回的对象。 如:document.getElementsByName()、document.images、document.links、document.forms、document.forms[0].elements
1.缓存length; for(var i = 0,max = arr.length;i<max;i++) 。如果arr是dom。速度会快很多倍。
2.var i,arr=[]; for(i = arr.length;i--;)
3.var arr = [],i=arr.length; while(i--){}
for in 主要用于非数组对象。 搭配 hasOwnProperty使用。
其他
switch case。 如果条件多。 可以用 var obj= {"case1":1,"case2":2,"case3":3}. 来代替。 obj['case1'];
不要增加内置原型。一定要增加请先检测是否存在该属性。
避免使用隐式类型转换。 要使用 ===。
使用 parseInt要约定 parseInt(year,10)。不要省略几进制。因为0开始的会当成8进制返回。
编码约定
缩进、大括号、空格
命名约定:构造函数的首字母大写
分割单词:大驼峰小驼峰下划线
函数与变量:全部大写字母用来表示常量不可改变、下划线开头来表示私有函数。
第三章、字面量和构造函数
来自构造函数的对象。
对象构造函数的捕捉。
自定义构造函数。在函数体中重新定义自己?
以new操作符调用构造函数的返回值:
1、如果没有return或return的直接量。返回this。(如果构造函数中并不向this添加任何属性,将返回“空”对象。)
2、如果有return对象。返回这个对象。
var this = Object.create(Person.prototype);
强制使用new模式:
1.返回一个想要的对象而不是this指代的对象。
2.自调用构造函数。 检测。if(!(this instanceof Person)){ return new Person()};
数组:
new Array(3) //长度为3
new Array(3.14) //error
检测是不是数组。 isArray
Object.prototype.toString.call([2,3])
"[object Array]"
JSON:
解析JSON: JSON.parse(jstr);$.parseJSON(jstr);eval('(+jstr+')');
序列化JSON: JSON.stringify(obj);
正则表达式
基本值类型包装器
错误对象。
第四章、函数
第一类对象。提供作用域。可调用。
函数就是对象。表现:
1.可运行时创建。
2.可分配给变量。
3.可当参数传递。
4.可添加属性和方法。
函数的命名属性。 .name。
函数的提升。
回调模式。 将函数当参数传递以备调用。
异步事件监听器。 大多数的客户端浏览器编程都是事件驱动的。
超时回调。
库中的回调模式。如jqery中的success。
返回函数。
自定义函数。
惰性函数。 函数第一次使用才真正被定义。自己给自己新的定义。
缺点:重定义时添加到原来函数的任何属性都会丢失。 引用丢失?
即时函数。 定义后立即执行。
作用域沙箱。
即时函数的参数传递。
即时函数的返回值。
即时对象的初始化 ({}).init();
初始化时分支。
跟自定义函数实现的效果有点像。 根据具体的情况。执行到那里,给函数合适的定义。 addEventListener与attachEvent浏览器嗅探。
函数属性。
备忘模式。 比如缓存计算结果。调用次数等等。
函数的length。值为期望参数的数量。
配置对象。 函数大量传参数的时候。 可以把多个参数放到一个 obj中传入。
curry:函数柯里化。 部分函数。
第五章、对象创建模式。
命名空间、依赖声明、模块模式、沙箱模式。
命名空间模式
var module1 = {}; module1.a = 1;
缺点:1.字多。2.长嵌套解析慢。
命名空间函数
var MYAPP = MYAPP ||{}。
写一个函数来创建空对象,添加属性。 MYAPP.namespace("MYAPP.a.b.c.d.e");
声明依赖关系
在函数顶部声明是不错的。 var event = MYAPP.a.event,dom = MYAPP.a.dom;
好处:1.一眼看出依赖。2.局部变量解析快。3.局部变量方便代码压缩。4.方便验证所需的脚本在不在页面中。
私有属性和方法。
可使用闭包实现属性和方法私有。
特权方法:可访问私有成员的方法。
私有性失效。
返回的变量是对象或数组。 那么外面可以访问甚至修改这个私有变量。
使用对象克隆。
对象字面量以及私有性
可以使用一个额外的即时函数创建闭包来实现私有性。
模块模式p97.
原型和私有性。prototype也可以用闭包这样子。
Person.prototype = ( function(){ var name = 1; return {getName:function(){ return name; } } } )();
将私有方法揭示为公有方法。
arr = {isArr:isArr,indexOf:indexOf}
模块模式: 命名空间 即时函数 私有和特权成员 声明依赖。
提示模块模式。
创建构造函数的模块。
将全局变量导入到模块中。()(MYAPP,this);
沙箱模式。
全局构造函数。
增加模块。
实现构造函数。
静态成员 从一个实例到另一个实例都不会发生改变的属性和方法。
公有静态成员
私有静态成员。
同一个函数创建,所有对象共享。 构造函数外不可访问。
对象常量
链模式。返回this。像jquery。
method方法。为对象创建方法。
第六章 代码复用模式
优先使用对象组合,而不是类继承。
基于类特性 和 基于非类特性 的 继承特性。
类继承模式
类继承模式1:
function inheirt(C,P){ C.prototype = new P(); }
原型属性应该指向一个对象而不是一个函数。
缺点:
1.继承了原型中的东西也继承了this上的属性。
2.不支持将参数传递到子构造函数中?
类继承模式2:借用构造函数。
function C(a,b,c){ P.apply(this,arguments); }
只继承了成员副本。没有继承原型里的东西。
借用构造函数实现多重继承。
类继承模式3:借用和设置原型。
就是上面两种方式加起来。
function C(a,b,c){ P.apply(this,arguments); } function inheirt(C,P){ C.prototype = new P(); }
类继承模式4:共享原型。
C.prototype = P.prototype;
类继承模式5:临时构造函数。
function inheirt(C,P){ var F = function(){}; F.prototype = P.prototype; C.prototype = new F; }
存储超类。上面的基础上增加指向原始父对象的引用。 C.uber = P.prototype;
重置构造函数指针。 C.prototype.constructor = C;
优化:使用闭包,只创建一次临时构造函数。
var inheirt = (function(){ var F = function(){}; return function inheirt(C,P){ F.prototype = P.prototype; C.prototype = new F; C.uber = P.prototype; C.prototype.constructor = C; } }())
无类继承模式
原型继承
function object(o){ function F(){} F.prototype = o; return new F(); } var kid = object(Person.prototype);
浅复制。
深复制。
jqery库中的extend()方法可实现深度复制。
混入。mix-in。 从多个对象中复制出任意成员组合成一个新对象。 效果有点像上面的 借用构造函数实现多重继承。
借用方法: apply call。
借用和绑定: bind。 将方法和对象绑定在一起。
可以使用闭包来实现。
function bind(o,m){ return function(){ m.apply(o,[].slice.call(arguments)); } }
if(typeof Function.prototype.bind==="undefined"){ Function.prototype.bind=function(thisArg){ var fn=this, slice=Array.prototype.slice, args=slice.call(arguments,1);//arguments1 return function(){ return fn.apply(thisArg,args.concat(slice.call(arguments)));//arguments2 } }; }
注意这个函数。 两个arguments 不是一样的。
要理解一下这个函数。
var t1 = one.say.bind(two); t1('haha');
var t2 = one.say.bind(two,'lala'); t2('lala')
代码复用才是最终目的,而继承只是实现这一目的的方法之一。
第七章.设计模式
单体模式。保证特定类只有一个实例。没有类,只有对象。
策略模式
支持你在运行时选择算法。一个例子是表单验证。
外观模式
两个或更多的方法可能普遍被一起调用。在这样的情况下,另建一个方法包装重复的方法调用。
例子:1.浏览器事件阻止。2.用来处理浏览器差异。把对不同浏览器的方法包装在一起。
代理模式
书中的例子用来合并http请求以及缓存请求数据的。
中介者模式
专门的部门负责对象之间的通信。http://www.jspatterns.com/book/7/mediator.html
观察者模式
订阅/发布模式。所有的浏览器事件是该模式的例子。
这种模式中,并不是一个对象调用另一个对象的方法,而是一个对象订阅另一个对象的特定活动并在状态改变后获得通知。
第八章、Dom和浏览器模式
DOM脚本、事件处理、远程脚本、页面载入JS的策略以及在网站上配置JS的步骤。
关注分离
js层应该不引人注意的,不应该因为浏览器不能使用js而影响正常使用。
js应该是用来加强网页功能,还不能成为网页正常工作的必需组件。
处理浏览器差异:特性检测技术。
DOM脚本。
不同的浏览器处理dom树方式可能不一样。所以才使用各种库来加快开发速度。
DOM访问 代价是昂贵的,是制约js性能的主要瓶颈。
dom通常是独立与js引擎而实现的。
远程脚本
ajax
jsonp(可跨域)
框架和图像灯塔。(可跨域)
配置JavaScript
var isIE = /*@cc_on!@*/false