如何写出高质量的Javascript代码

优秀的Stoyan Stefanov在他的新书中(《Javascript Patterns》)介绍了很多编写高质量代码的技巧,比如避免使用全局变量,使用单一的var关键字,循环式预存长度等等。

这篇文章不仅仅从代码本身来考虑如何优化编码,也从代码的设计阶段来考虑,包括书写API文档,同事的review,使用JSLint。这些习惯都能帮助你编写更加高质量的、更易于理解的、可维护的代码(让你的代码在多年之后仍使你引以为傲)。

编写可维护的代码

软件的BUG修复需要花费大量的精力。尤其当代码已经发布之后,随着时间的增长,维护的成本愈发的高。当你一发现BUG的时候,就立即去修复,这时候你的代码还是热乎的,你也不需要回忆,因为就是刚刚写好的。但是当你做了其他任务,几乎完全忘记了这份代码,这时候就需要:

  1. 重新学习和理解问题
  2. 理解代码是如何解决问题的
    另外一个问题是,在大项目或者大公司里面,经常是解决BUG的人不是产生BUG的人,而且也不是发现BUG的人。所以减少理解代码的时间就是最重要的问题,无论这个代码是你自己以前写的还是团队中的其他成员写的,因为我们都想去搞搞新的有意思的东西,而不是去维护那些个陈旧的代码。

还有一个开发中的普遍问题就是,往往读代码的时间比写代码的时间还要多。有时候你钻研一个问题,可以花整整一个下午的时间来考虑代码的编写。这个代码当时是可以工作的,但是随着开发的进行,其他东西发生了很大的变化,这时候也就需要你自己来重新审查修改编写代码。比如:

  1. 还有BUG没有解决
  2. 添加了新的功能
  3. 程序需要在新的环境中运行(比如一个新上市的浏览器)
  4. 代码有问题
  5. 代码需要重写因为修改了架构甚至要使用另一个语言
    因为这些原因,也许你当时一个下午写好的代码,后面需要花费几周的时间来阅读。所以编写可维护的代码对于软件的成功至关重要。

可维护的代码包括:

  1. 可读性
  2. 连续性
  3. 预见性
  4. 看起来是一个人写的
  5. 有文档
  6. 最少化全局变量
    Javascript使用函数来约定作用域。一个在函数内部声明的变量在外部是不可见的。所以,全局变量也就是声明在任何函数之外的或者没有被声明的变量。

Javascript中,在任何函数之外有个可访问的全局对象,每一个你创建的全局变量都是这个对象的一个属性。在浏览器中,为了方便,通常用window来指代这个全局变量。下面的代码就是说明如何创建一个全局变量:

myglobal = "hello"; // antipattern
> console.log(myglobal); // "hello"
> console.log(window.myglobal); // "hello"
> console.log(window["myglobal"]); // "hello"
> console.log(this.myglobal); // "hello

全局变量的问题

全局变量的问题在于,他在你的所有代码或者一个页面中都共享。他们在同一个命名空间下面,这通常会造成变量名冲突–两个同名的变量,但是确实不同的用处。

通常在一些页面中需要引入一些其他人的代码,比如:

  1. 第三方的JS库
  2. 广告伙伴的脚本
  3. 第三方的用户行为分析或者统计脚本
  4. 不同的组件、按钮等等
    加入其中一个第三方组件定义了一个全局变量:result。然后在你的程序中,也定义了一个全局变量result。最后的这个result会覆盖点之前的result,这样第三方的脚本就会停止工作。

所以,为了对其他的脚本友好,在一个页面中使用越少的全局变量越好。在后面会有一些方法来告诉你如何减少全局变量,比如使用命名空间,或者自执行的匿名函数,但是最好的避免全局变量的方法就是使用var关键字来声明变量。

使用navigator.geolocation来获取用户的地理位置信息

W3C 中新添加了一个名为 Geolocation的 API 规范,Geoloaction API的作用就是通过浏览器获取用户的地理位置。我们可以使用navigator.geolocation来简单的获取用户的地理位置信息。本文中将简单介绍下W3C的Geolocation。

Geolocation在javascript的navigator 对象中,我们可以通过 navigator.geolocation 来使用它。不支持 geolocation 的浏览器并不包含这一对象,那么可以通过下面的代码来做能力检测,对不同的浏览器做不同的处理。

if (navigator.geolocation) {
        alert( ' 浏览器支持 geolocation ' );
}else{
        alert( ' 浏览器不支持 geolocation ' );
}

在访问 geolocation 对象时,即调用 geolocation 下面的方法时,浏览器会弹出提示,询问用户是否许可网站提供的位置服务,只有在得到用户许可过后,服务才会继续,否则将被停止,在稍后你将会了解到,我们能够捕获到用户拒绝服务的动作。下面这张图分别是 Chrome , Firefox 和 Opera 在初次访问 geolocation 时,给用户的提示:

初次使用geolocation时的警告框

常用的navigator.geolocation对象有以下三种方法:

  1. 获取当前地理位置:navigator.geolocation.getCurrentPosition(success_callback_function, error_callback_function, position_options)
  2. 持续获取地理位置:navigator.geolocation.watchPosition(success_callback_function, error_callback_function, position_options)
  3. 清除持续获取地理位置事件:navigator.geolocation.clearWatch(watch_position_id)
    其中success_callback_function为成功之后处理的函数,error_callback_function为失败之后返回的处理函数,参数position_options是配置项,由JSON格式传入:

  4. enableHighAccuracy:true/false,它将告诉浏览器是否启用高精度设备,所谓的高精度设备包含但不局限于前面所提到的 GPS 和 WIFI,值为 true 的时候,浏览器会尝试启用这些设备,默认指为 true,在这种情况下,浏览器会尽可能地进行更为精确的查询,简单地说,如果用户有可用的 GPS 设备,会返回 GPS 设备的查询结果,IP 是最后的选择,对于移动设备来说,网络接入点(基站)或许成为另一个选择,对此我还没有完全了解,但根据测试,即时没有任何额外功能的手机,也能够得到更为精确的查询结果。

  5. maximumAge:单位毫秒,告诉设备缓存时间,主要用于设备的省电或者节省带宽方面。
  6. timeout:单位毫秒,超时事件,获取位置信息时超出设定的这个时长,将会触发错误,捕获错误的函数将被调用,并且错误码指向TIMEOUT。

例如下面的代码:


var geo=navigator.geolocation.getCurrentPosition(geo_success, geo_error, {enableHighAccuracy:true, 
    maximumAge:30000, 
    timeout:27000});

三种常见jQuery幻灯片(jQuery slider)制作教程

好久没正儿八经的写写js代码了,再不写就生疏了,昨天无意中发现cityhouse的首页幻灯片有问题,于是今天就写了三个幻灯片实例,如果还不会用jquery写幻灯片的可以参考我之前的文章:《CSS+jQuery实现滑动幻灯片实例详解》以及两个jQuery幻灯片实例

今天的三个jQuery幻灯片其实还是两个,只不过第一种滚动的幻灯片有两种形式:分别是上下滚动和左右滚动。兼容IE6+,FF,chrome等主流浏览器。
效果和淘宝首页的幻灯片效果相同,自动播放时是一直往一个方向前进。
布局方面还算比较简洁,大家可以根据自己的需要添加内容,另外这次的幻灯片加上了文字,其实不光图片可以slider,文字也可以slider一会的。另外加了一点CSS3,就是控制按钮圆角化了(FF3.6+和chrome下有效果)。

截图

三种常见jQuery幻灯片(jQuery slider)实例

教程

iframe自适用高度代码

有不少wBox的用户反映iframe时候不可以自动撑开高度,今天在无意中看到了司徒正美的一片关于iframe自适用高度的js代码,感觉不错,转载来了。


var adjustIframe = function (id) {
    var iframe = document.getElementById(id)
    var idoc = iframe.contentWindow && iframe.contentWindow.document || iframe.contentDocument;
    var callback = function () {
        var iheight = Math.max(idoc.body.scrollHeight, idoc.documentElement.scrollHeight); //取得其高
        iframe.style.height = iheight + "px";
    }
    if (iframe.attachEvent) {
        iframe.attachEvent("onload", callback);
    } else {
        iframe.onload = callback
    }
}

前端必须熟悉的10个CSS3属性

随着Css3和html5的风靡,越来越多的前端人员开始学习Css3,今天的文章就是来说说前端应该掌握10个Css3属性。 上篇博文提到了《前端必须掌握30个CSS3选择器》,但是对于Css3的新属性,你又了解多少呢?虽然大多数的css3属性在很多流行的浏览器中不支持,但是我们鼓励在前端开发中要学会并且运行这些css3属性,因为这是未来的趋势。 关键是首先确定你是否对各个浏览器之间的细微的差别有所了解,你能肯定的说IE显示的90度的角就不圆滑嘛?这取决于你的决定。但是要永远记住,网站设计不必看到所有浏览器的不同。在文章的最后,我们将显示一个有趣的最终的案例。

1、border-radius

border-radius

border-radius是一大堆CSS3属性中最受欢迎的一种,border-radius是CSS3中级别最高的一个属性。当设计者害怕一个层在将在不同的浏览器之间以不同的方式显示时,CSS圆角,一个很初级的知识,将引导他们开始学习。 我们为移动浏览器提供一个备用的观看体验的想法都非常好。奇怪的是,当这种方法出现在桌面浏览器上时,他们却又不这么认为。 border-radius是一大堆CSS3属性中最受欢迎的一种,border-radius是CSS3中级别最高的一个属性。当设计者害怕一个层在将在不同的浏览器之间以不同的方式显示时,CSS圆角,一个很初级的知识,将引导他们开始学习。 我们为移动浏览器提供一个备用的观看体验的想法都非常好。奇怪的是,当这种方法出现在桌面浏览器上时,他们却又不这么认为。


-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;

注意:请在Safari 5 和 IE9浏览器中执行”border-radius”语法。

许多读者也许不会意识到我们可以用这个属性来做一个圆。

前端必须掌握30个CSS3选择器

也许你已经学会了CSS的三个简单常用的选择器:#ID,.class,标签选择器,可是这些就足够了吗?随着CSS3的到来,作为前端开发者需要掌握下面三十个基本的选择器,这样才可以在平时开发中得心用手。

本文中将综合前端开发中常用的30个CSS3选择器,并且附带了浏览器的支持情况,希望对大家有所帮助。

1、*:通用元素选择器


* {  
 margin: 0;  
 padding: 0;  
} 

*选择器是选择页面上的全部元素,上面的代码作用是把全部元素的margin和padding设为0,最基本的清除默认CSS样式方法

*选择器也可以应用到子选择器中,例如下面的代码:


#container * {  
 border: 1px solid black;  
} 

这样ID为container 的所有子标签元素都被选中了,并且设置了border。

查看演示

兼容性
  1. IE6+
  2. Firefox
  3. Chrome
  4. Safari
  5. Opera

#ID:ID选择器


#container {  
   width: 960px;  
   margin: auto;  
}  

ID选择器是CSS中效率最高的选择器,使用的时候要保证ID的唯一性。

查看演示

兼容性
  1. IE6+
  2. Firefox
  3. Chrome
  4. Safari
  5. Opera

.class:类选择器


.error {  
  color: red;  
}  

类选择器效率低于ID选择器,一个页面可以有多个class,并且class可以放在不同的标签中使用。

查看演示

CSS3 Media Queries使用方法详解

在css2中允许我们使用media的属性,例如使用screen和print,我也写过一篇关于使用CSS media的print来定义打印网页的样式的文章,关于css2中的media文章,推荐下w3c的。今天来说说CSS3的Media Queries。CSS3中不仅仅可以使用screen和print,而且支持多媒体多分辨率的样式表。

我们先来看下CSS3 Media Queries的演示实例:http://js8.in/mywork/css3media.html,来自于(Web Designer Wall

Max Width

故名思意,就是最大宽度的意思,例如下面的代码是在宽度小于600px的时候才执行的。

@media screen and (max-width: 600px) {
  .class {
    background: #ccc;
  }
}

也可以在link标签里面使用media属性,即下面的写法:


<link rel="stylesheet" media="screen and (max-width: 600px)" href="small.css" />

Min Width

跟Max Width相反,是最小宽度,例如当宽度大于900px的时候才运行下面的代码

@media screen and (min-width: 900px) {
  .class {
    background: #666;
  }
}

javascript简单实现checkbox的全选与反选

今天上网遇到有个网友在论坛问input的checkbox全选和反选的问题,顺手总结了一下,然后写了个简单的jQuery checkbox全选反选插件,希望对大家有用。
如果是简单的实现checkbox的全选与反选可以使用下面的函数:


 function checkall(obj,cName)
 {
     var checkboxs = document.getElementsByName(cName);
     for(var i=checkboxs.length;i--;){
             checkboxs[i].checked = obj.checked;
     }
 }
//使用方法:给全选的按钮加onclick事件:onclick="checkall(this,'all[]');"

再谈Iframe的问题

iframe是可以做的事情非常多,比如通过iframe实现跨域,使用iframe解决IE6下select遮挡不住的问题,通过iframe解决Ajax的前进后退问题,再比如通过iframe实现异步上传。在很早我就写过一篇文章说明了Iframe在IE、firefox下的一些DOM操作。今天结合最近项目中遇见的iframe问题,再来谈谈iframe的一些常见问题解决方案。

IE下iframe背景透明问题

在firefox下,iframe背景默认的是透明的,在IE下默认不是透明的,我们可以使用allowTransparency='true'来设置IE下的iframe为透明,另外我们使用scrolling ='no' `frameborder=’0’`分别来实现iframe页面没有滚动条,边框宽度。

IE6下iframe不显示的问题

不得不说IE6是个操蛋的浏览器,尤其是在中国!iframe有的时候在IE6中会出现不显示的问题,主要有以下几种原因,请一一排查:

  1. 可能你的iframe没有设置宽高,例如在table不居中,计算不出来td的高度,会导致这种问题
  2. 尝试使用下面的代码来重新载入IE6下的iframe页面:
    `javascript

setTimeout(function(){
document.frames[‘fuckIE6’].location.reload();
},0)
`

  1. 传闻iframe标签中不要把src紧跟在iframe之后,也就是&lt;iframe src='js8.in' name='fuckIE6'&gt;&lt;/iframe&gt;是错误的,不过我没有碰见过类似的问题,为了保险起见,还是不要写成上面的样式为妙。

jQuery教程之鼠标事件篇

jQuery除了选择器之外,还封装了很多事件的处理,比如鼠标事件,所谓的鼠标事件是指用户在移动鼠标光标或者点击任意鼠标键而触发的事件,jQuery中封装了几乎所有的鼠标事件,包括点击,双击,移出,移入等鼠标事件,下面断桥残雪简单的介绍下jQuery的鼠标事件

jQuery的click事件

经典鼠标click的实例:


$("sel").click(function(){
    alert('哈哈 !');
});

jQuery的dbclick事件

一般dbclick事件的同时也会触发两次click事件。。以前我写过一篇博客简单的介绍了下jQuery的鼠标双击事件


$('p').dbclick(function(){
alert('鼠标双击!');
});
$('p').click(function(){
alert('点击了一下!');
});//大家看看结果是怎么样的?