每次去图书馆都能随手带两本不错的书回来。看了不少书。有不少收益。慢慢总结笔记。发现一次看很多本书,更容易理解书里的概念。
第一章
基本概念:
模式: 重现事件或对象的主题……是一个可用来产生其他事物的模板或模型。
好处: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 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]) 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也可以用闭包这样子。
将私有方法揭示为公有方法。 arr = {isArr:isArr,indexOf:indexOf} 模块模式: 命名空间 即时函数 私有和特权成员 声明依赖。 提示模块模式。 创建构造函数的模块。 将全局变量导入到模块中。()(MYAPP,this); 沙箱模式。 全局构造函数。 增加模块。 实现构造函数。 静态成员 从一个实例到另一个实例都不会发生改变的属性和方法。 公有静态成员 私有静态成员。 同一个函数创建,所有对象共享。 构造函数外不可访问。 对象常量 链模式。返回this。像jquery。 method方法。为对象创建方法。 第六章 代码复用模式 优先使用对象组合,而不是类继承。 基于类特性 和 基于非类特性 的 继承特性。 类继承模式 类继承模式1: 原型属性应该指向一个对象而不是一个函数。 缺点: 1.继承了原型中的东西也继承了this上的属性。 2.不支持将参数传递到子构造函数中? 类继承模式2:借用构造函数。 只继承了成员副本。没有继承原型里的东西。 借用构造函数实现多重继承。 类继承模式3:借用和设置原型。 就是上面两种方式加起来。 类继承模式4:共享原型。 C.prototype = P.prototype; 类继承模式5:临时构造函数。 存储超类。上面的基础上增加指向原始父对象的引用。 C.uber = P.prototype; 重置构造函数指针。 C.prototype.constructor = C; 优化:使用闭包,只创建一次临时构造函数。 无类继承模式 原型继承 浅复制。 深复制。 jqery库中的extend()方法可实现深度复制。 混入。mix-in。 从多个对象中复制出任意成员组合成一个新对象。 效果有点像上面的 借用构造函数实现多重继承。 借用方法: apply call。 借用和绑定: bind。 将方法和对象绑定在一起。 可以使用闭包来实现。 注意这个函数。 两个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
编码约定
缩进、大括号、空格
命名约定:构造函数的首字母大写
分割单词:大驼峰小驼峰下划线
"[object Array]"
Person.prototype = (
function(){
var name = 1;
return {getName:function(){
return name;
}
}
}
)();
function inheirt(C,P){
C.prototype = new P();
}
function C(a,b,c){
P.apply(this,arguments);
}
function C(a,b,c){
P.apply(this,arguments);
}
function inheirt(C,P){ C.prototype = new P(); }
function inheirt(C,P){
var F = function(){};
F.prototype = P.prototype;
C.prototype = new F;
}
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;
}
}())
Klass。
function object(o){
function F(){}
F.prototype = o;
return new F();
}
var kid = object(Person.prototype);
通过复制实现继承
function bind(o,m){
return function(){
m.apply(o,[].slice.call(arguments));
}
}
[].slice.call(arguments)这句话相当于Array.slice.call(arguments),目的是将arguments对象的数组提出来转化为数组,arguments本身并不是数组而是对象 p142.
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
}
};
}
w3c的标准stopPropagation()与IE特有的方法 cancelBubble.
事件授权 事件委托?