作者:kun10
发布时间:May 15, 2011
分类:JavaScript
JSHint介绍
翻译自www.jshint.com
JSHint(注意不是jslint:))是一个由javascript社区驱动开发的用于检查javascript代码错误和问题的工具,有了他,可以使你保持一个良好的编码风格。你可以很简单的配置它以适应你目前的一个编码风格。
目前JSHint的源码可以在github上面找到。
JSHint文档
如何使用JSHint
JSHint是一个全局的函数,他接受两个参数,
JSHint(source,options);
一个是代码source,另一个是options(选项)
第一个参数可以是一个字符串或者是一个字符串数组。如果是字符串,则他会被\n和\r分割,如果传入的参数是数组,就要保证数组的每一项是一行代码。
因此源码参数可以是javascript代码或者是一个json形式。如果所有的检测都ok,JSHint会返回true,否则就返回false。
当返回false的时候,你可以用JSHint.errors来获取错误信息或者用JSHint.data()来获取lint的信息。
如果要了解更多,参见源代码。
使用JSHint,你可以在js文件的开始设定选项,例如
/*jshint evil:true, boss:true */
而设定global参数可以告诉JSHint,全局的变量配置。
例如
/*global DISQUS: true, jQuery: false */
以上的这个例子是告诉JSHint,DISQUS是你自己声明的全局变量,而jQuery是你引入的全局变量
JSHint和JSLint有什么区别?
JSHint是
JSLint的一个分支(fork),他比JSLint更加的便捷。用来约束你的代码质量和编码风格。
每个人都有不一样的编码习惯和风格,JSHint通过配置可以适应于各种情况。
JSHint的适用环境
- 浏览器环境(browsers)
- Node.js
- jQuery
- ES5
- CouchDB
- Prototype.js
- Mootools.js
JSHint的选项配置
asi
如果是真,JSHint会无视没有加分号的行尾,
自动补全分号一直是Javascript很有争议的一个语法特性。默认,JSHint会要求你在每个语句后面加上分号,但是如果你认为自己理解了asi(automatic semicolon insertion),你可以抛弃JSHint对分号的检查。
bitwise
如果为真,JSHint会禁用位运算符
Javascript允许位运算,但是他却没有整型,位运算符要把参与运算的数字从浮点数变为整数,并在运算后再转换回来。这样他们的效率就不如在别的语言中那么高。
boss
很霸气的选项,如果为真,那么JSHint会允许在if,for,while里面编写赋值语句。
一般来说,我们会在循环、判断等语句中加入值的比较来做语句的运行条件,有时候会把==错写成赋值的=,通常,JSHint会把这个认定为一个错误,但是开启这个选项的化,JSHint就不会检查判断条件中的赋值 ,你是boss,你说的算:)。
curly
如果为真,JSHint会要求你在使用if和while等结构语句时加上{}来明确代码块。
Javascript允许在if等结构语句体只有一句的情况下不加括号。不过这样做可能会让你的代码读起来有些晦涩。
debug
如果为真,JSHint会允许代码中出现debugger的语句。不过建议你最好在检测代码前去掉debug的语句。
eqeqeq
如果为真,JSHint会看你在代码中是否都用了===或者是!==,而不是使用==和!=。
我们建议你在比较0,''(空字符),undefined,null,false和true的时候使用===和!===。
eqnull
如果为真,JSHint会允许使用"== null"作比较。
== null 通常用来判断一个变量是undefined或者是null(当时用==,null和undefined都会转化为false)。
evil
如果为真,JSHint会允许使用eval
eval提供了访问Javascript编译器的途径,这有时很有用,但是同时也对你的代码形成了注入攻击的危险,并且会对debug造成一些困难。
记住,Function构造函数也是另一个‘eval’,另外,当传入的参数是字符串的时候,setTimeout和setInterval也会类似于eval。
forin
如果为真,那么,JSHint允许在for in 循环里面不出现hasOwnProperty,
for in循环一般用来遍历一个对象的属性,这其中也包括他继承自原型链的属性,而hasOwnProperty可以来判断一个属性是否是对象本身的属性而不是继承得来的。
immed
如果为真,JSHint要求匿名函数的调用如下:
(function(){
//
}());
而不是
(function(){
//bla bla
})();
laxbreak
如果为真,JSHint则不会检查换行。
Javascript会通过自动补充分号来修正一些错误,因此这个选项可以检查一些潜在的问题。
maxerr
设定错误的阈值,超过这个阈值jshint不再向下检查,提示错误太多。
newcap
如果为真,JSHint会要求每一个构造函数名都要大写字母开头。
构造器是一种使用new运算符来创建对象的一种函数,new操作符会创建新的对象,并建立这个对象自己的this,一个构造函数如果不用new运算符来运行,那么他的this会指向全局对象而导致一些问题的发生。
noarg
如果为真,JSHint会禁止arguments.caller和arguments.callee的使用
arguments对象是一个类数组的对象,它具有一个索引值。arguments.callee指向当前执行的函数(这个在ES5的严格模式中被禁用了),而arguments.caller指向调用当前函数的函数(如果有的话),并且,他并不是在所有的Javascript实现里面都有。
noempty
如果为真,JSHint会禁止出现空的代码块(没有语句的代码块)。
如果为真,JSHint会禁用构造器,以避免一些问题。
在
JSLint中会主动禁用构造器的方式以避免一些潜在问题,但其实很多构造器的使用并非有害,例如如下的调用
new JsUIWindow();
//注意这个调用是没有把构造器的结果赋值给变量的
因此,我们需要使用构造器的时候可以禁用这个选项。
nomen
如果为真,JSHint会禁用下划线的变量名。
很多人使用_name的方式来命名他们的变量,以说明这是一个私有变量,但实际上,并不是,下划线只是做了一个标识。
如果要使用私有变量,可以使用闭包来实现。
onevar
如果为真,JSHint期望函数只被var的形式声明一遍。
passfail
如果为真,JSHint会在发现首个错误后停止检查。
plusplus
如果为真,JSHint会禁用自增运算和自减运算
++和--可能会带来一些代码的阅读上的困惑。
regexp
如果为真,JSHint会不允许使用.和[^...]的正则,
因为这样的正则往往会匹配到你不期望的内容,并可能会应用造成一些危害。
undef
如果为真,JSHint会要求所有的非全局变量,在使用前都被声明。
如果你不在一个本地作用域内使用var的方式来声明变量,Javascript会把它放到全局作用域下面。这样会很容易引起错误。
sub
如果为真,JSHint会允许各种形式的下标来访问对象。
通常,JSHint希望你只是用点运算符来读取对象的属性(除非这个属性名是一个保留字),如果你不希望这样可以关闭这个选项。
strict
如果为真,JSHint会要求你使用use strict;语法。
Strict 模式是ES5里面的一个新特性,他允许你把一个程序或者函数放在一个“严格”的作用域中。可见Resig写的
一篇关于严格模式的blog严格模式做了几件事情,
1、他可以捕获一些错误和异常
2、当我们进行一下“不安全”的操作时,他会抛异常,例如访问全局变量。
3、他会禁止你使用一些奇淫技巧,或者不良的代码编写。
white
如果为true,JSHint会依据严格的空白规范检查你的代码。
转载请注明出处~
作者:kun10
发布时间:May 3, 2011
分类:JavaScript
什么是javascript里面的ArrayLike对象?
一切都是源于看YUI的Array部分,Y.Array()方法本身就能把对象转化为数组的方法,接受一个叫arraylike的参数。
其实arraylike我们经常会遇到,函数的arguments对象就是一个最常见的arraylike对象。
我们可以在firebug里面console.log一个函数的arguments对象,会发现他是一个对象,不是会发现他带有一个length属性。
但是我们却不能用普通的数组的方法来操作arguments对象
比如:
arguments.pop();//arguments.pop is not a function
很奇特吧?其实arraylike的对象还不只arguments对象一个
document.getElementsByTagName(), document.images, document.childNodes这几个货都是arraylike的对象。
既然这些对象是arraylike的,我们自然很渴望使用array的方法来操作他们。
方法很早就有人写了。
var newArray = Array.prototype.slice.call(arguments);
原理:
Array.prototype.slice: The original slice method that is given to all arrays via the prototype chain. We can’t call it directly though, because when it runs internally, it looks at the this keyword, and calling it here would make this point to Array, not our arguments variable.
Array.prototype.slice.call(): call() and apply() are prototype methods of the Function object, meaning that they can be called on every function in javascript. These allow you to change what the this variable points to inside a given function.
中文注解:
Array.prototype.slice是Array原型上面的slice方法,因为Arraylike对象不是array,所以直接使用slice是无效的,因此我们要把我们的arguments对象作为this,传入slice方法中。如何传入slice方法,我们使用call方式来把arguments作为this传给slice做处理。call和apply是Function构造函数对象的原型方法,因此我们可以对任意的函数使用。this最终被函数处理成一个数组。
这在非IE的情况下面好使,因为在IE下面domnodelist不被认为是对象,对于IE我们只能使用慢一点的方法了。
var newArray = [];
for(var i = 0;i< arguments.length;i++){
arr.push(arguments[i]);
}
return newArray;
此时newArray就是一个数组对象。
我们可以对他pop(),push()等等等等。。。
参考:
http://nfriedly.com/techblog/2009/06/advanced-javascript-objects-arrays-and-array-like-objects/(这篇更靠谱点。。。)
http://shifteleven.com/articles/2007/06/28/array-like-objects-in-javascript
作者:kun10
发布时间:May 1, 2011
分类:JavaScript
原文地址:here
译者:qiaofu
去年我们发布了YUI test 的1.0beta1版本,之后我们便进行了反馈的收集,bug的修补以及补充新特性。今天我很高兴的宣布我们的beta2版本也发布了,这将是我们在通用版本前的最后一个版本。新的beta2版本的发布拥有一些新的核心功能,例如对Node.js的初步支持。所有的这一切都是为了创建一个更完整的测试解决方案,方便你在任何地方进行javascript的测试。
核心的变化
基于来自YUI社区的反馈,我们对YUI Test的核心做了一些补充。首先是加入了测试用例对象的初始化(init())和销毁的方法(destroy()),而在此之前,我们一直用setUp和tearDown来做数据的初始化和销毁。在传统的xUnit形式的测试框架中,setUp用来在每一个测试前运行,而tearDown则是运行于每一个之后。init和destroy则是分别运行于测试用例对象中所有setUp()方法之前和tearDown方法之后,并都只运行一次。这两个方法有利于管理整个贯穿于整个用例对象的数据。例如:
var testCase = new YUITest.TestCase({
name: "TestCase Name",
//---------------------------------------------
// init and destroy
//---------------------------------------------
init : function () {
this.data = {
name : "Nicholas",
age : 28
};
},
destroy : function () {
delete this.data;
},
//---------------------------------------------
// Tests
//---------------------------------------------
testName: function () {
YUITest.Assert.areEqual("Nicholas", this.data.name, "Name should be 'Nicholas'");
},
testAge: function () {
YUITest.Assert.areEqual(28, this.data.age, "Age should be 28");
}
});
另一个变化是“上下文数据”(context data)特性的引入。当一个测试(testRunner)开始,他会创建一个对象,这个对象会被传递到每一个init方法、setUp方法、destroy方法以及tearDown方法和test方法里面,默认情况这个对象是空的。你可以利用他在多个测试用例对象和方法之间共享一些数据。例如:
var testSuite = new YUITest.TestSuite({
name: "Test Suite Name",
setUp: function(data){
data.topLevel = 1;
}
});
testSuite.add(new YUITest.TestCase({
name: "First Test Case",
init: function(data){
data.foo = "bar";
},
testValueOfFoo : function (data) {
YUITest.Assert.areEqual("bar", data.foo);
//数据来自init
},
testValueOfTopLevel: function(data){
YUITest.Assert.areEqual(1, data.topLevel);
//数据来自测试套件
}
});
testSuite.add(new YUITest.TestCase({
name: "Second Test Case",
testValueOfFoo : function (data) {
YUITest.Assert.areEqual("bar", data.foo);
//数据来自第一个测试用例的init
},
testValueOfTopLevel: function(data){
YUITest.Assert.areEqual(1, data.topLevel);
//数据来自测试套件
}
});
当然最关键的一点,如何使用好上下文数据取决于你自己,即便不用它你也可以很好的完成测试的工作。
针对Node.js的YUI Test
在YUI test beta2里面,我们增加了对Node.js的支持,你可以利用如下命令安装
~:npm install yuitest
一旦安装完成,你就可以传入测试文件和被测试文件的路径,进行测试。
~:yuitest testfile.js path/to/test
在浏览器中写javascript测试和在Node.js里面写javascript测试的区别在于,浏览器端的js测试,你需要在测试页面中引入yui test文件,Nodejs中你需要require引入YUItest。而利用一下的形式你可以在浏览器端和Node.js端用同一套脚本
(function(){
//define local version of YUITest based on what's available.
var YUITest = this.YUITest || require("yuitest");//引入YUITest,这句是关键
var testCase = new YUITest.TestCase({
//test case details
});
YUITest.TestRunner.add(testCase);
})();
如果是浏览器端引入yuitest文件,那么this.YUITest应该会指向window对象下面的YUITest,否则就是用NodeJs的require方式来引入yuitest。
不过有一点要注意的是,Node.js环境里面并没有Dom,因此dom部分很可能在node.js下面抛出异常(译者YY:这一点或许安装了Node.js的jsdom会解决问题)
展望通用版本
要达到GA版本我们还有很多要做,还有很多的bug要修复,定制更好的说明文档以及跟进社区里面提及的重要点。blablabla...
- 1