编写高质量代码:Web前端开发修炼之道(三)

10 篇文章 0 订阅
4 篇文章 0 订阅

第五章:高质量的Javascript

这章的内容我看的最久,这是跟我js基础没打好有着莫大的关系,但是还是耐着性子看完了, 不懂的东西都是百度上搜索,理解后再继续。下面是记录下来的笔记。

1)如何避免JS冲突

A:匿名函数

在多人合作一个网站时,每个人都会写自己的JS代码,定义变量的时候有可能会引起命名冲突,如何避免这种冲突隐患呢?

一种最简单有效的办法是“匿名函数”将脚本包起来,让变量的作用域控制在匿名函数之内

匿名函数:(function (){})() 前面的括号内是函数体,后面的()表示执行。

如:(function(){

  var name,user="test";      //包含在这个匿名函数中的变量,作用域不再是window,而是局限在函数内部。 因为各自包在不同的匿名函数内,也就不再互相冲突了。

  })();

用匿名函数将脚本包起来,可以有效的控制全局变量,避免冲突隐患。

B:解决匿名函数之间的通信问题

上面的匿名函数确实解决了冲突,但是如果两个代码段之间需要访问彼此的变量,那就被分隔开了,没法访问对方作用域中的变量.

一个比较好的解决办法是"在window的作用域下定义一个全局变量",但是从上面的冲突来看,全局变量是引起冲突的杀手,如果又这样定义,就违背了我们使用匿名函数的初衷,所以应该严格控制全局变量的数量!

为了控制全局变量的数量,用Hash对象作为全局变量。  var GLOBAl={};  //一个对象类型的变量作为全局变量,扩展性好

定义好对象类型变量后,在匿名函数A中定义GLOBAL的属性:GLOBAL.str1="aaa";   在匿名函数B中可以直接访问var b = BLOBAl.str1;

这样又出现了一个问题,当在匿名函数B中它也定义一个属性BLOBAl.str1="bbb"; 这个时候就会把A块中的属性str1给覆盖掉.如何避免这种冲突呢?不可能每个开发者在使用GLOBAL对象之前,都要查找一下绑定了哪些属性。

这时,命名空间就出现了,它是一种特殊的前缀,在js中它其实是通过一个{}对象来实现的。我们可以给每个匿名函数声明不同的命名空间,然后每个匿名函数中GLOBAL对象的属性不要直接挂在GLOBAl对象上,而是挂在此匿名函数的命名空间下,既:window全局的GLOBAL.命名空间.属性变量  ,这样申明属性名称的时候,即使同名,空间不一样也不会引起冲突。如:GLOBAL.A={};// 定义命名空间; GLOBAL.A.str1="aaa";//定义属性变量

复杂的匿名函数中,你还可以生产二级命名空间,如GLOBAL.A={};//一级命名空间,GLOBAL.A.CAT={};GLOBAL.A.DOG={};//二级命名空间;

生成命名空间是一个很常用的功能,可以将其封装为一个函数。

var GLOBAL={};

GLOBAL.namespace=function(str){

  var arr=str.split("."),o=GLOBAL;

  for(i=(arr[0]=="GLOBAL")?1:0; i<arr.length; i++){

    o[arr[i]]=o[arr[i]] || {};

    o=o[arr[i]];

  }

}    

调用: GLOBAL.namespace(A.DOG);      GLOBAL.namespace(GLOBAL.B);

总结:解决js冲突-------命名空间+全局变量+匿名函数 很好的结合使用才能更好的解决冲突。

C:注释

添加必要的代码注释,可大大提高可维护性,对团队合作来说,是很重要的。

注释添加的信息包括:功能说明;工程师姓名;工程师联系方式;代码最后修改时间;

让JS不产生冲突,需要避免全局变量的泛滥,合理使用命名空间,以及给代码添加注释。

 

2)JS代码程序统一入口---------window.onload和DOMready

JS从功能上分为两部分:1 框架部分(提供的是对JS代码的组织作用,包括定义全局变量,命名空间等,和具体的应用无关,该部分被每个页面都包括的)---base层,common层;

                               2 应用部分(页面功能逻辑的代码段,不同页面有不同的功能,不同页面应用部分的代码也不同)---page层;

而应用部分的代码最好包在一个约定好的入口函数里,(程序统一入口,是针对js应用部分来说的),一般初始化的部分会放在一个统一的函数function init(){}中,然后在页面完全加载完毕后触发;

window.onload:需要在页面完全加载完成时才会触发,包括图片,flash等富媒体,

DOMReady:只需要判断页面内所有的DOM节点是否已经完成加载,至于节点的内容加载是否完成,他并不关心。

所以DOMReady触发的速度比window.onload快,它比window.onload更适合用来调用初始化函数。【我一般使用jquery,所以页面加载完毕会用$(fuction(){...});或$(document).ready(function(){...});】

另外一种模拟Ready的效果是将初始化的js代码块 放在body结束标签的前面js ...</body>,这样会按照顺序来载入。

 

3)CSS放在页头,JS放在页尾

浏览器加载网页,加载到JS时,由于脚本比较多,而html代码还没有加载,这是页面会显示空白,脚本阻塞了html的加载,等到毫不容易加载完成了,有时候会发现这些网页元素没有样式,所以一个好的习惯是,CSS放在页头,JS放在页尾(先加载css,再加载html,再加载js.) 这样就能适时的将界面呈现给用户,减少页面空白的时间。

 

4)引入编译的概念---------文件压缩

JS压缩通常的做法是去掉空格和换行,去掉注释,将复杂变量名替换为简单的变量名;压缩后的js文件的确变小了,但是压缩后的文件无法反压缩恢复成原来的模样。

压缩命名规则:原名.js    压缩后的名为:原名-min.js

 

5)js 如何分层----------(为了使代码更清晰,减少冗余,提高代码重用率)

和css分层一样:base层:最低端,两个职责:1:不同浏览器之间js的差异提供统一接口;2:扩展js语言底层提供的接口,比如tostring...  

            base层是给common层和page层提供接口的。

        common层:提供可复用的组件,和页面内具体功能无关。common层的功能是给page层用的;

        page层:最顶端,该层主要是完成各个页面内的功能需求。

A:base层

琐碎知识点:

1:IE和FF下获取childNodes会不一样,因为FF会将包括空白、换行等文本信息业当做childNodes中的一员,而IE会忽略它,只将DOM节点作为childNodes的一员。

2:document.all是IE支持的属性,FF 不支持,通常也可以用来判断浏览器的种类。

3:nextSibling:获取某个节点的下一个同级节点。

获得某个父节点下面的子节点,然而浏览器不一样,为了兼容,会根据浏览器做出一些处理,将处理封装成函数,像这类函数将放到base层。如:getnextnode(node)

4:透明度:IE通过滤镜实现,FF通过css的opacity属性实现。node.style.filter='alpha(opacity='3')'; nodel.style.opacity=0.3;

5:event:  IE中event对象是window的属性,作用于全局作用域,在FF中,event是作为事件的参数存在。

一般 function(e){e=window.event||e;}//这样e在IE和FF下都指向event对象。

event对象的部分属性名在IE和FF下也是不同的,比如"触发事件的对象(标签)"在IE下通过srcElement属性访问,在FF下通过target访问

var element= e.srcElement ||e.target;

6: 冒泡:两个重叠的标签点击其中一个时,另外一个也会被触发点击事件,JS 将这种先触发子容器监听事件,再触发父容器监听事件的现象称为冒泡。

    为了业务需要,我们需要阻止事件冒泡,在IE中通过设置event对象的cancelBubble属性为true实现,在FF下通过调用Event对象的stopPropagation方法实现的。

if(document.all){

   e.cancelBubble=true;//IE

}else{

  e.stopPropagation();//FF

}

7:on、attachEvent和addEventListener

我们在定义事件时,往往on**只能定义一次,如果再次定义,就会覆盖前面定义好的方法。最常见的为onclick事件。

on***的监听方式没有叠加效果,最后定义的on***会将前面的事件覆盖掉。

attachEvent(IE支持的方法)、addEventListener(FF支持的方法),他们支持监听处理函数的叠加。

例:btn.attachEvent("onclick",function(){...});     btn.addEventListener("click",function(){...});

总结:以上1-7点中,为了兼容不同浏览器而封装的一些兼容处理函数,像这类函数将放到base层。如:getnextnode(node)

8:扩展Js语言底层的接口

例:trim() isNumber() isString() get() $() extend()等等 

base层的JS和页面里的具体应用逻辑无关,属于框架级的。

B:common层

common层本身依赖于base层提供的接口,需要先加载base层代码。它与base层的区别是:common层不是简单的接口,而是相对庞大的组件。(如:设置和获取cookie,就可以封装cookie组件). 它和具体功能相关,如果页面里不需要相关功能,就没必要加载,而一个易用性和可扩展性都好的组件,代码量会偏高,所以一般common层的js要按功能分成一个个单独的文件,如common_cookie.js,common_drag.js,common_tab.js.

common层的JS和页面里的具体应用逻辑无关,属于框架级的。

C:page层

base层和common层都是属于框架级的,page层是属于应用级的,它可以调用base层的接口和common层的组件 

 

6) js类库

常见的有prototype. Dojo, Mootools,Extjs,jquery,yui等。这么多我用的比较多的是jquery   ,好像extjs也不错,以后有空学习学习。

 

转载请注明出处

原文地址:http://www.cnblogs.com/Joans/archive/2012/09/12/2681550.html 

kindle高清文字版,可在电脑上用clearview电子书阅读软件阅读。 第1章 从网站重构说起 1.1 糟糕的页面实现,头疼的维护工作 1.2 Web标准——结构、样式和行为的分离 1.3 前端的现状 1.4 打造高品质的前端代码,提高代码的可维护性——精简、重用、有序 第2章 团队合作 2.1 揭秘前端开发工程师 2.2 欲精一行,必先通十行 2.3 增加代码可读性——注释 2.4 提高重用性——公共组件和私有组件的维护 2.5 冗余和精简的矛盾——选择集中还是选择分散 2.6 磨刀不误砍柴工——前期的构思很重要 2.7 制订规范 2.8 团队合作的最大难度不是技术,是人 第3章 高质量的HTML 3.1 标签的语义 3.2 为什么要使用语义化标签 3.3 如何确定你的标签是否语义良好 3.4 常见模块你真的很了解吗 3.4.1 标题和内容 3.4.2 表单 3.4.3 表格 3.4.4 语义化标签应注意的一些其他问题 第4章 高质量的CSS 4.1 怪异模式和DTD 4.2 如何组织CSS 4.3 推荐的base.css 4.4 模块化CSS——在CSS中引入面向对象编程思想 4.4.1 如何划分模块——单一职责 4.4.2 CSS的命名——命名空间的概念 4.4.3 挂多个class还是新建class——多用组合,少用继承 4.4.4 如何处理上下margin 4.5 低权重原则——避免滥用子选择器 4.6 CSS sprite 4.7 CSS的常见问题 4.7.1 CSS的编码风格 4.7.2 id和class 4.7.3 CSS hack 4.7.4 解决超链接访问后hover样式不出现的问题 4.7.5 hasLayout 4.7.6 块级元素和行内元素的区别 4.7.7 display:inline-block和hasLayout 4.7.8 relative、absolute和float 4.7.9 居中 4.7.10 网格布局 4.7.11 z-index的相关问题以及Flash和IE 6下的select元素 4.7.12 插入png图片 4.7.13 多版本IE并存方案——CSS的调试利器IETester 第5章 高质量的JavaScript 5.1 养成良好的编程习惯 5.1.1 团队合作——如何避免JS冲突 5.1.2 给程序一个统一的入口——window.onload和DOMReady 5.1.3 CSS放在页头,JavaScript放在页尾 5.1.4 引入编译的概念——文件压缩 5.2 JavaScript的分层概念和JavaScript库 5.2.1 JavaScript如何分层 5.2.2 base层 5.2.3 common层 5.2.4 page层 5.2.5 JavaScript库 5.3 编程实用技巧 5.3.1 弹性 5.3.2 getElementById、getElementsByTagName和getElements-ByClassName 5.3.3 可复用性 5.3.4 避免产生副作用 5.3.5 通过传参实现定制 5.3.6 控制this关键字的指向 5.3.7 预留回调接口 5.3.8 编程中的DRY规则 5.3.9 用hash对象传参 5.4 面向对象编程 5.4.1 面向过程编程和面向对象编程 5.4.2 JavaScript的面向对象编程 5.4.3 用面向对象方式重写代码 5.5 其他问题 5.5.1 prototype和内置类 5.5.2 标签的自定义属性 5.5.3 标签的内联事件和event对象 5.5.4 利用事件冒泡机制 5.5.5 改变DOM样式的种方式 附录A 写在规则前面的话 附录B 命名规则 附录C 分工安排 附录D 注释规则 附录E HTML规范 附录F CSS规范 附录G JavaScript规范
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值