JavaScript编程事项和技巧
首次为变量赋值时务必使用关键字var
如果没有声明直接赋值的话,默认会作为一个新的全局变量,要尽量避免使用全局变量
使用 === 替代 ==
==和!=操作符在有需要的情况下会自动转换数据类型但 === 不会,而且他会同时比较值和数据类型。速度更快
undefined、null、0、false、NaN,空字符串的逻辑结果均为 false
虽然JavaScript语法识别换行,但为了压缩还是在行尾加上分号
使用对象构造器
function Person(firstName,lastName){
this.firstName=firstName;
this.lastName=lastName;
}
var Saad=new Person("Saad","Mousliki");
小心使用 typeof、instanceof 和 constructor
- typeof:JavaScript 一元操作符,用于以字符串的形式返回变量的原始类型,注意,typeof null 也会返回object,大多数的对象数据类型(数组Array、时间Date等) 也会返回 Object
- contructor:内部原型属性,可以通过代码重写
- instanceof:JavaScript操作符,会在原型链中的构造器搜索,找到则返回true,否则返回false
var arr=["a","b","c"];
typeof arr; //返回 object
arr instanceof Array; //返回 true
arr.constructor(); //返回 []
使用自调用函数
函数在创建之后直接自动执行,通常称为自调用匿名函数或直接调用函数表达式。格式如下:
(function(){
//置于此处的代码将自动执行
})();
(function(a,b){
var result=a+b;
return result;
})(10,20);
从数组中随机获取成员
function getRandomFormArray(){
var items=[12,13,14.15,16,17,18,20];
var randomItem=items[Math.floor(Math.random()*items.length)];
return randomItem;
}
获取指定范围内的随机数
function getRangeRandom(min,max){
var x=Math.floor(Math.random()*(max-min+1))+min;
return x;
}
生成从0到指定值得数字数组
function getIntegerRangeAarry(max){
var numbersArray=[];
for(var i=1;numbersArray.push(i++)<max;);
return numbersArray;
}
生成随机的字母数字字符串
function getGenerateRandomAlphaNum(len){
var rdmString="";
for(;rdmString.length<len;rdmString+=Math.random().toString(36).substring(2));
return rdmString.substr(0,len);
}
打乱数字数组的顺序
function upsetArray(){
var numbers=[5,458,120,-215,228,400,1222505,-48545];
numbers=numbers.sort(function(){return Math.random()-0.5});
return numbers;
}
字符串去空格
String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"");};
数组追加
var array1=[12,"f00",{name:"Joe"},-2458];
var array2=["Doe",555,100];
Array.prototype.push.apply(array1,array2);
对象转换为数组
var argArray=Array.prototype.slice.call(arguments);
验证是否是数字
function isNumber(n){
return !isNaN(parseFloat(n)) && isFinite(n);
}
验证是否是数组
function isArray(obj){
return Object.prototype.toString.call(obj)==='[object Array]';
}//这个 方法有个bug,如果toString()方法被重写过就行不通,可以用下面这个方法:
Array.isArray(obj); //its a new Array method
获取数组中的最大值和最小值
var numbers=[5,458,-215,228,400,1252524];
var maxInNumbers=Math.max.apply(Math,numbers);
var minInNumbers=Math.min.apply(Math,numbers);
清空数组
var myArray=[12,222,1000];
myArray.length=0; //myArray will be equal to []
不要直接从数组中delete或 remove元素
解释一下:如果数组中直接使用delete,其实并没有删除元素,而是将元素设置为undefined,数组删除元素用splice。 删除对象属性时可以用delete
var items=[12,548,'a',2,5478,'foo',8852,'Doe',2154,119];
items.splice(3,1); //从元素'a'开始起删除下一个元素。
使用length属性阶段数组
解释一下:length 不仅可以用来清空数组,同样还可以来截断数组:
var myArray=[1,2,3,4,5,6];
myArray.length=5; //myArray will be equal to [1,2,3,4,5]
myArray.length=7; //myArray will be equal to [1,2,3,4,5,undefined,undefined]
逻辑与、或的作用
var foo=10;
foo==10 && doSomething(); //等同于 if(foo==10) doSomething();
foo==5 || doSomething(); //等同于 if(foo!=5) doSomething();
foo=12 || foo; //这里用逻辑或 设置优先级或者 默认值,优先级从左到右
使用map() 函数方法对数据循环
var squares=[1,2,3,4].map(function(val){
return val*val;
}); //squares 将变成 [1,4,9,16];
保留指定小数位数
var num=2.44324545225;
num=num.toFixed(4); //num将变成 2.4432
浮点计算的问题
0.1+0.2====0.3 //false
通过for-in循环检查对象的属性
for(var name in object){
//do something with name
}
逗号操作符
var a=0;
var b=(a++,99); // a变成1 b变成99
临时存储用于计算和查询的变量
在jQuery选择器可以临时存储整个DOM元素
var aa=$('#aa');
提前检查传入isFinite()的参数
isFinite(0/0); //false
isFiNITE("foo"); //false
isFinite("10"); //true
isFinite(10); //true
isFinite(undefined); //false
isFinite(); //false
isFinite(null) //true,这个特别注意
避免在数组中使用负数做索引
var numbersArray=[1,2,3,4,5];
var from=numbersArray.indexOf("foo"); //-1
numbersArray.splice(from,2); //[5]
用JSON来序列化和反序列化
var person={name:'Saad',age:26,department:{ID:15,name:'R&D'}};
var stringFormPerson=JSON.stringify(person); //结果为:{"name":"Saad","age":26,"department":"{"ID":15,"name":"R&D"}}"
var personFromString=JSON.parse(stringFormPerson); //personFromString的值与person对象相同
不要使用eval()或者函数构造器
eval()和函数构造器(Function constructor)的开销较大,每次调用,都要将源码转换为可执行的代码。
避免使用with()
使用with()可以把变量加入到全局作用域中,因此,如果存在其他的同名比变量,一来容易混淆,而来值也可能会被覆盖。
不要对数组使用for-in,对象可以
加快循环执行效率的小方法:(减少初始化次数)
var arrayA=[1,2,3,4,5,6]
var sum=0;
for(var i=0,len=arrayA.length;i<len;i++){
sum+=arrayA[i];
}
传给setInterval()和setTimeout()时使用函数而不是字符串
解释一下:因为如果传字符串。他们将会进行类似于eval方式的转换,这肯定会要慢点,因此不要使用。正确的写法是传函数名,如下:
setInterval(doSomethingPeriodically,100);
setTimeout(doSomethingAfterFiveSeconds,5000);
使用switch/case 代替 一大堆 if/else
当判断有超过两个分支的时候使用switch/case 要更快一些,而且也更优雅,更有利于代码的组织,当然,如果有超过10个分支,就不要使用switch/case 了。
在switch/case中使用数字区间
function getCategory(age){
var category="";
switch(true){
case isNaN(age):
category="not an age";
break;
case (age>=50):
category="Old";
break;
case (age<=20):
category="Baby";
break;
default:
category="Young";
break;
}
return category;
}
getCategory(5); //返回 Baby
使用对象作为对象的原形
把给定对象作为参数,来创建以此为原型的新对象:
function clone(object){
function oneShotConstructor(){};
oneShotConstructor.prototype=object;
return new oneShotConstructor();
}
clone(Array).prototype; //[]
HTML字段转换函数
function escapeHTML(text){
var replacements={"<":"<",">":">","&":"&","\":"""};
return text.replace(/[<>&"]/g,function(character){
return replacements[character];
});
}
不要在循环内部使用try-catch-finally
try-catch-finally中catch部分在执行时将会将异常赋给一个变量,这个变量会被构成一个运行时作用域内的新的变量。
var object=['foo','bar'],i;
错误写法:
for(i=0,len=object.length;i<len;i++){
try{
//do something that throws an exception
}
catch(e){
//handle exception
}
}
正确的写法:
try{
for(i=0,len=object.length;i<len;i++){
//do something that throws an exception
}
}
catch(e){
//handle exception
}
使用XMLHttpRequests时注意设置超时
XMLHttpRequests时,当长时间执行没有响应,应该中断,可以通过setTimeout()来完成这个工作:
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(this.readyState==4){
clearTimeout(timeout);
//do something with response data
}
}
var timeout=setTimeout(function(){
xhr.abort();//call error callback
},60*1000);
xhr.open('GET',url,true);
xhr.send();
同时需要注意的是,不要同时发起多个XMLHttpRequests请求。
处理WebSocket的超时问题
通常情况下,websocket连接创建后,如果30秒内没有任何活动,服务器端会对连接进行超时处理,防火墙也可以对单位周期没有活动的连接进行超时处理。为了防止这种情况发生,可以每隔一段时间,往服务器端发送一条空的消息。可以用下面两个函数来实现这个需求,一个用于使连接保持活动状态,另一个专门用于结束这个状态。
var timerID=0;
function keepAlive(){ //放在WebSocket连接的onOpen()方法的最后面
var timeout=15000;
if(webSocket.readyState==webSocket.OPEN){
webSocket.send('');
}
timerId=setTimeout(keepAlive,timeout);
}
function cancelKeepAlive(){ //放在onClose()方法的最末尾
if(timerId){
cancelTimeout(timerId);
}
}
原始操作符比函数调用快
比如:
var min=Math.min(a,b);
A.push(v);
/*可以代替为:*/
var min=a<b?a:b;
A[A.length]=v;
常用的JavaScript检查和压缩工具
- JSLint
- JSMin