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

第五章:高质量的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 

转载于:https://www.cnblogs.com/lxzltg/p/5104037.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491376.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV矩阵操作

矩阵类的成员函数可以进行很多基本的矩阵操作&#xff0c;在之前已经介绍过。除此之外&#xff0c;也有很多操作被表示为“友元”函数&#xff0c;它们的输入为矩阵类型&#xff0c;或者输出为矩阵类型&#xff0c;或者输入输出同为矩阵类型。下面将对这些函数及其参数进行详细…

LaTeX Error: Unknown graphics extension: .eps.解决办法

只要加一个包就行了&#xff01; \usepackage{epstopdf}

Android Studio中获取SHA1或MD5的方法

原来在Eclipse中获取SHA1或者MD5&#xff0c;在IDE界面上就可以查找到。 切换到Android Studio后&#xff0c;如何查看呢&#xff1f;找了半天没找到。那就老办法命令行。 第一步、打开Android Studio的Tools->Open Terminal... 第二步、输入命令&#xff1a;keytool -v -li…

关于机器意识的对话

来源&#xff1a; 人机与认知实验室S教授德高望重&#xff0c;建立了一个关于人工智能的微信群&#xff0c;吸引了很多关心人工智能的专业人士参与讨论。群中常有热烈的讨论。前些天恰好有一场关于机器意识的对话。感觉比较有意思&#xff0c;觉得放任这些讨论在微信群里被遗忘…

OpenCV绘图和注释

OpenCV的绘图函数可以在任意深度的图像上工作&#xff0c;但在大多数情况下&#xff0c;它们只对图像的前三个通道有影响BGR&#xff0c;如果是单通道图像&#xff0c;则默认只影响第一个通道。大多数绘图函数都支持操作对象的颜色、宽度、线型和亚像素对齐等参数。 艺术线条 …

012.对netmap API的解读

一.简要说明&#xff1a; 1.netmap API主要为两个头文件netmap.h 和netmap_user.h &#xff0c;当解压下载好的netmap程序后&#xff0c;在./netmap/sys/net/目录下&#xff0c;本文主要对这两个头文件进行分析。 2.我们从netmap_user.h头文件开始看起。 二.likely()和unlikely…

如何查看图片的长和宽(尺寸)

用PS打开该图片——>图像——>图像大小

【学术笔记】探索大脑静息态活动中的动态信息

来源&#xff1a;脑科学2019年6月18日下午&#xff0c;来自加州大学河滨分校(The University of California, Riverside) Bourns工程学院的生物工程系主任Xiaoping Hu (胡小平)教授应北京大学麦戈文脑研究所方方老师的邀请来到北京大学&#xff0c;在王克桢楼1113室为老师和同学…

OpenCV中的函数子

随着OpenCV的发展&#xff0c;封装了越来越多的功能&#xff0c;而往往这些功能不是一个函数就能完成的&#xff0c;实现为一组函数又会导致整个库的函数变得杂乱无章&#xff0c;因此常常使用一个新的对象类型来实现这个新功能。通过重载operator()来生成对象或函数子。下面主…

查找会议论文的会议地址

有时候会议论文conference proceedings引用格式中要求出现会议地址&#xff0c;如下所示 查找会议地址的方法为直接搜索该会议论文&#xff0c;以ieee为例&#xff0c;会议地址信息在该论文的首页信息中&#xff1a; Conference Location: Arlington, VA, USA中的三项就分别对应…

jqGrid API 全

JQGrid是一个在jquery基础上做的一个表格控件&#xff0c;以ajax的方式和服务器端通信。 JQGrid Demo 是一个在线的演示项目。在这里&#xff0c;可以知道jqgrid可以做什么事情。下面是转自其他人blog的一个学习资料&#xff0c;与其说是学习资料&#xff0c;说成查询帮助文档更…

OpenCV可移植图形工具HighGUI实现图像和视频操作

OpenCV把用于操作系统、文件系统以及摄像机等硬件设备交换的函数纳入了HighGUI&#xff08;High-level Graphical User Interface&#xff09;模块中。有了HighGUI模块&#xff0c;我们可以方便地打开窗口、显示图像、读出或写入图像相关的文件、鼠标事件和键盘事件。下面将对三…

华为内部深度解读,关于5G发展的28个核心问题

来源 | 腾讯深网关于5G技术动态与商用进展业界最关心的核心问题&#xff0c;华为5G产品线相关负责人近日对《深网》等进行了详细解读&#xff0c;以下是《深网》整理的问答实录&#xff1a;一、5G先进性与行业应用1. 5G到底是什么&#xff1f;和4G比有什么不一样&#xff1f;从…

福昕阅读器截屏

菜单栏中的照相机按钮即为截屏工具

OpenCV鼠标事件和滑动条事件

鼠标事件 ① 鼠标事件是通过传统的回调函数机制来完成。 void your_mouse_callback(int event, int x, int y, int flags, void* param) 其中&#xff0c;第一个参数要指明事件&#xff0c;第二个和第三个参数是鼠标事件的位置&#xff0c;第四个参数是标志位&#xff0c;第…

《需求分析与系统设计》第三篇

规则和描述性引用完整性约束允许在数据库中定义简单的业务规则&#xff0c;触发器是一个小程序&#xff0c;当定义了触发器的表发生修改操作是自动执行&#xff08;触发&#xff09;。数据库就像程序设计语言一样&#xff0c;为建模和程序设计提供了固有数据类型作为基本构造块…

GSMA:中国有望成为全球领先的5G市场之一

来源&#xff1a;GSMA移动智库近日&#xff0c;GSMA&#xff08;全球移动通信协会&#xff09;发布首个《中国移动经济发展报告2019》。报告称&#xff0c;中国的移动生态系统在2018年为中国经济创造了5.2万亿元 (7,500亿美元) 的附加值&#xff0c;相当于2018年中国GDP的5.5%。…

查期刊名缩写网站

http://cassi.cas.org/search.jsp

canal —— 阿里巴巴mysql数据库binlog的增量订阅消费组件

阿里巴巴mysql数据库binlog的增量订阅&消费组件canal &#xff0c;转载自 https://github.com/alibaba/canal 最新更新 canal QQ讨论群已经建立&#xff0c;群号&#xff1a;161559791 &#xff0c;欢迎加入进行技术讨论。canal消费端项目开源: Otter(分布式数据库同步系统…

OpenCV的滤波与卷积

目录 预备知识 滤波、核和卷积 边界外推和边界处理 阈值化操作 Otsu算法 自适应阈值 平滑 简单模糊和方框型滤波器 中值滤波器 高斯滤波器 双边滤波器 导数和梯度 索贝尔导数 Scharr滤波器 拉普拉斯变换 图像形态学 膨胀和腐蚀 通用形态学函数 开操作和闭操…