【读书笔记】读《编写高质量代码—Web前端开发修炼之道》
搬出来之前的学习笔记,我觉得还算可以的一本基础书籍。
先弄个这本书的logo——
目录结构——
第一章:从网站重构说起
第二章:团队合作
第三章:高质量的HTML
第四章:高质量的CSS
第五章:高质量的JavaScript
其核心内容如下——
第一章:从网站重构说起
/** * 1.分离结构、样式、行为 * 2.打造高品质的前端代码,提高代码的可维护性—— * 1>精简:可以让文件变小,有利于客户端快速下载; * 2>重用:可以让代码更易于精简,同时有助于提升开发速度; * 3>有序:可以让我们更清晰地组织代码,使代码更易于维护,有效应对变化。 */
第二章:团队合作
/** * 1.一专多能:欲精一行,必先通十行 * 2.增加代码可读性——注释 * 3.公共组件和私有组件的维护 * 1>公共组件需要专人来维护,要注意限制“写”的权限,提供API和演示DEMO; * 2>私有组件对于修改操作会自由得多,但是必要的注释还是需要的 * 3>在组织公共组件时,组织的粒度越大,文件越集中,加载和管理越方便,但无用代码越多。(如jQuery框架) * 4>在组织公共组件时,组织的粒度越小,文件越分散,加载和管理越麻烦,但无用代码越少。(如YUI框架) * 5>因此,在“集中”与“分散”上,我们需要找到不错的平衡点。 * 4.磨刀不误砍柴工——前期构思很重要 * 1>先根据用户需求进行分析,先考虑好框架,会让整个开发过程更有规划、更流畅,是一个先慢后快的过程。 * 2>构思内容: * (1)规范的制定 * (2)公共组件的设计 * (3)复杂功能技术实现方案 * 5.制定规范 * 有效指导团队成员按照一个统一的标准进行开发,尽量让开发过程平滑,减少不必要的冲突,提高开发率并保证软件的质量。 */
第三章:高质量的HTML
/** * 1.如何确定标签语义是否良好 * 去掉样式,看网页结构是否组织良好有序,是否仍然有很好的可读性 * 2.常见模块 * 1>标题内容模块 * 2>表单模块 * 3>表格模块 * 3.其他 * 1>尽可能少地使用无语义标签div和span * 2>不使用纯样式标签(如b/font/u等) */
第四章:高质量的CSS
/** * 1.怪异模式和DTD * 1>为了确保向后兼容,浏览器厂商发明了标准模式和怪异模式这两种方法来解析网页 * 标准模式:浏览器根据规范表现页面 * 怪异模式:通常模拟老式浏览器(比如IE4和Netscape Navigator 4)的行为以防止老站点无法工作,在该模式下 * (1)width包含border和padding * (2)margin: 0 auto;无法达到居中效果 * 可用这两点来判断浏览器是否是处于怪异模式(尤其是针对IE) * 2>DTD:Document Type Definition,即文档类型定义。DTD是一种保证HTML文档格式正确的有效方法, * 可以通过比较HTML文档和DTD文件来看文档是否符合规范,以及元素和标签使用是否正确。 * 一个DTD文档包含元素的定义规则、元素间关系的定义规则、元素可使用的属性、可使用的实体或符号规则。 * 如果漏写DTD声明,Chrome/Firfox/Safari/Opera仍然会按照标准模式来解析网页,但在IE中(IE6/7/8)就会触发怪异模式。 */
/** * 2.如何组织CSS * 将网站内的所有样式,按照职能分成3大类:base、common、page * 1>这三者是层叠结构 * 2>base层:提供CSS reset功能和力度最小的通用原子类。 * 这一层与具体UI无关,无论何种风格的设计都可以引用它,所以base层要力求精简和通用。 * 3>common层:位于中间,提供组件级的CSS类。 * 将页面内的元素拆分成一小块一小块功能和样式相对独立的小“模块”; * common是网站级的,不同的网站有不同的common层 * 4>page层:非高度重用的模块 * page层位于最高层,提供页面级的样式。 */
/** * 3.模块化CSS * 1>单一职责 * (1)模块与模块之间尽量不要包含相同的部分,如果有相同部分,应将它们提取出来,拆分成一个独立的模块; * (2)模块应在保证数量尽可能少的原则下,做到尽可能简单,以提高重用性。 * 2>命名空间 * css命名空间的概念 * <div class="box"> * <div class="box-hd"></div> * <div class="box-bd"></div> * <div class="box-ft"></div> * </div> * 可以将这里的box命名理解为一个类的类名称(也就是模块名称),而这里的hd/bd/ft正是box里面的(私有)变量, * box内部样式的修改并不会影响box模块外的样式,可以理解为这里的box起到了命名空间的作用。 * 3>多用组合、少用继承 * (1)能够大大减少类的数量,提高了可维护性; * (2)使类的职责更单一,弹性更强,增加了类的重用性,提高了开发效率。 * 当然,这种方式会让HTML标签看起来过于臃肿,但是它带来的好处确实不容忽视的,推荐挂多了class的方式 * 4>处理上下margin * 如果不确定模块的上下margin特别稳定,最好不要将它写到模块的类里,而是使用类的组合, * 单独为上下margin挂用于边距的原子类。模块最好不要混用margin-top和margin-bottom, * 统一使用margin-top或margin-bottom。 */
/** * 4.常见问题 * 1>为了保证样式容易被覆盖,提高可维护性,CSS选择符需保证权重尽可能低。 * 2>CSS sprite * 在网站流量限制及维护性上找到一个平衡点 * 3>CSS编码风格(一行式、多行式) * 笔者倾向于一行式,个人倾向于多行式 * 4>class和id * 尽量使用class,少用id * 5>CSS hack(IE条件注释法、选择符前缀法、样式属性前缀法) * 个人倾向于样式属性前缀法 * 6>display: inline-block和haslayout * 能够触发IE6/IE7(其本身并不支持display: inline-block)行内元素的haslayout. * 7>relative、absolute、float * (1)position: relative;会保留自己在z-index:0层的占位, * 其left/right/top/bottom值是相对于自己在z-index:0层的位置 * (2)position: absolute;会完全脱离文档流,不再在z-index:0层保留占位符, * 其left/right/top/bottom值是相对于自己最近的一个设置了position: relative;或 * postion: absolute;的祖先元素,如果发现没有,那么就相对于body元素了。 * (3)float: left/right;属性不会让元素“上浮”到另一个z-index层,它仍然让元素在z-index层排列, * float会改变正常的文档流排列,影响到周围元素。 * 8>水平居中和垂直居中 * 9>网格布局(grid-xxx-xx、layout-xxx-xx、content-xxx-xx) * 10>z-index和IE6下的select元素 * */
第五章:高质量的JavaScript
/** * 1.防止JS冲突 * 1>用匿名函数(自执行)将脚本抱起来,可以有效控制全局变量,避免冲突隐患。 * 2>让JS不产生冲突,需要避免全局变量的泛滥,合理使用命名空间以及为代码添加必要的注释。 * * 2.JS分层思想 * 1>base层 * 位于三层中的最底端,具有两个职责。其一,封装不同浏览器下JavaScript的差异,提供统一的接口。 * 其二,扩展JavaScript语言底层提供的接口,让它提供更多更为易用的接口。 * 2>common层 * 位于三层的中间,依赖于base层提供的接口。common层提供可供复用的组件,它是典型的MVC模式中的M, * 和页面内的具体功能没有直接关系。common层的功能是给page层提供组件。 * 3>page层 * 位于三层的顶端。这一层和页面里的具体功能需求直接相关,是MVC模式中的C。 * page层依赖于base层和common层。page层的功能是完成页面内的功能需求。 * 拿YUI2和jQuery组件库举例子: * YUI2本身分成三大部分:Core、Utilities、Widget,其对应分层如下 * Core --> base层 * Utilities --> common层 * Widget --> common层 * jQuery本身分成两大部分:jQuery核心文件和jQuery UI文件,后者依赖于前者,其对应分层如下 * jQuery核心 --> base层 * jQuery UI --> common层 * * 3.编程实用技巧 * 1>弹性 * 思考如何让自己的代码具备很高的扩展弹性,思考让自己的代码更具应对需求变化。 * 2>多用className进行功能相似点的程序挂钩而不是标签名 * 3>用hash对象来替代类似于test(3, null, null, 5)传递参数的方式,就不用过于遵循参数传递的顺序及个数问题 * 一律用hash映射方式进行传参,应用接收参数的时候可读性也增加了一些。整体而言更加灵活。 */
/** * 4.面向过程编程 * 1>这种编程方式将程序分成了“数据”和“处理函数”两个部分,程序以“处理函数”为核心, * 如果要执行什么操作,就将“数据”传给相应的“处理函数”,返回我们需要的结果。这种编程方式就是面向过程编程。 * 2>这种编程方式存在的问题如下: * (1) 数据和处理函数之间没有直接的关联,在执行操作的时候,我们不但要选择相应的处理函数, * 还要自己准备处理函数需要的数据,也就是说,在执行操作的时候,我们需要同时关注处理函数和数据。 * (2) 数据和处理函数都暴露在同一个作用域内,没有私有和公有的概念,整个程序中所有的数据和处理函数都可以相互访问, * 在开发阶段初期也许开发速度很快,但到了开发后期和维护阶段,由于整个程序耦合得非常紧, * 任何一个处理函数和数据都有可能关联到其他地方,容易牵一发而动全身,从而加大了修改难度。 * (3) 面向过程的思维方式是典型的计算机思维方式——输入数据给处理器,处理器内部执行运算,处理器返回结果。 * 也就是说面向过程的思维方式是在描述一个个“动作”。 * 而现实生活中的一个个“物件”(如人{姓名,状态})很难用面向过程的思维方式进行描述。 * (4) 当代码量很大的时候,“数据”和“处理函数”之间的耦合度大大增加,不利于维护。 */ //面向过程编程的典型例子 //定义电话本 var phonebook = [ {name: 'adang', tel: '1111'}, {name: 'king', tel: '2222'} ]; //查询电话 function getTel(phoneBook, name) { var tel = ''; for (var i = 0; i < phoneBook.length; i++) { if (phoneBook[i].name === name) { tel = phoneBook[i].tel; break; } } return tel; } //调用函数 getTel(phonebook, 'king'); /** * 面向对象编程 * 这种编程就是抛开计算机思维,使用生活中的思维进行编程的编程方式。面向过程的思维就是描述一个个“动作”, * 而面向对象的思维就是描述一个个“物件”,客观生活中的物件,在程序中我们管“物件”叫做“对象”, * 对象由两部分组成:“属性”和“行为”,对应客观世界中物件的“状态”和“动作”。 */ //下面看看面向过程编程和面向对象编程的区别 //面向过程 var name = 'king', state = 'awake'; say = function (oname) { alert('I am ' + oname); }, sleep = function (ostate) { ostate = 'asleep'; }; say(name); sleep(state); //面向对象 var king = { name: 'king', state: 'awake', say: function () { //在对象内部,对象的属性和行为通过this关键字关联起来 alert('I am ' + this.name); }, sleep: function () { this.state = 'asleep'; } } //在对象外部,属性和行为可以用对象的属性和对象的行为来调用,从而让程序有了按真实世界的思维方式进行描述的能力。 king.say(); king.sleep(); /** * 一个典型的OO编程过程应该是先整理需求,根据需求进行OOA(面向对象分析),将真实世界的客观物件抽象成程序中的类或对象, * 这个过程经常会用到的是UML语言,也称UML建模,OOA的输出结果是一个个类或对象的模型图。接下来要进行OOD(面向对象设计), * 这一步的关键是处理类之间的耦合关系,设计类或对象的接口,此时会用到各种设计模式。OOA和OOD是反复迭代的过程, * 他们本身也没有非常清晰的边界,是相互影响、制约的。OOA和OOD是面向对象编程的思想和具体语言无关,而OOP(面向对象的程序设计) * 是面向对象编程的工具,和选用的语言相关。 */
/** * 5.其他问题 * 1.prototype和内置类 * 1> 我们可以通过扩展prototype原型能够扩展内置类的方法,要记住扩展方法中的this代表的是实例化的对象。 * 2> 我们不但可以扩展内置类的方法,还可以重写内置类的方法。 * 3> 修改内置类的原型在多人合作时可能对别人的代码造成影响,存在冲突隐患 * 2.标签的自定义属性 * 1> 从兼容性考虑,对于常规属性,统一使用node.xxx的方式读取,对于自定义属性,统一使用node.getAttribute('xxx')读取 * 2> 自定义属性的反序列化 * <a id="a" href="http://www.cnblogs.com/jinguangguo/" bloginfo="{name:'king', type:'WEB前端开发'}">my blog<\/a> * <script> * var node = document.getElementById(a); * var info = node.getAttribute('bloginfo'); * info = eval('(' + info + ')'); * alert(info.name); //king * alert(info.type); //WEB前端开发 * <\/script> * 3> 标签的内联事件和event对象 * (1)在IE下,event是window对象的一个属性,是在全局作用于下的,而在Firefox里,event对象作为事件的参数存在 * (2)代码段一如下 * <a href="#" id="a">链接<\/a> * <script> * document.getElementById('a').onclick = function () { * alert(arguments.length); //IE:0;非IE:1 * }; * <\/script> * (3)代码段二如下 * <a href="#" id="a" onclick="handle()">链接<\/a> * <script> * function handle() { * alert(arguments.length); //all browser:0 * } * <\/script> * (4)代码段三如下 * <a href="#" id="a" onclick="alert(event.type);">链接</a> //all browser:click * 4> 利用事件冒泡机制 * 冒泡的思路是在祖先节点上监听事件,有效减小内存开销 * 5> 改变DOM样式的三种方式 * (1)直接设置style * (2)添加预先设定的类 * (3)添加预先设定的css文件(通常用于全站皮肤设定的类似功能) */