javascript中小方法

1、尽量少甚至避免使用全局变量:
javascript中全局变量的危害已经被各大网友所痛斥,在此就不多说了,我就结合自己的开发经验浅谈一下如何处理和避免使用javascript中的全局变量。

a) 给必须要使用的全局变量名前加上一个固定的前缀,比如:_result、_username等;

b) 定义一个全局变量对象,用来存放项目所有的全局变量,比如:var global = {} ,以后只要定义global.username= “snoopyxdy”;来定义全局变量,这样既不污染命名空间,也很利于程序员调用和识别全局变量,而且可以很方便的查看所有全局变量。

c) 把需要直接运行的脚本放入闭包,这样既可以避免全局变量被其他脚步覆盖掉,又可以提高代码执行效率,定义局部变量是最快,最高效的一种方式。例如:

var global
var x = “22222222”; (红色的这个分号不能省略,否则会报错)
(function(){
var x=”11111111”; //11111111
alert(x);
})()
alert(x) //22222222

上面这个例子闭包内的代码可以很好的独立运行,而闭包外的代码也可以正常的运行,不会因为互相覆盖变量值而出错。

另外(function(){})()等效于~function(){}();~和()一样.都是强制运算的作用. 如果没有它们的话,即functon(){}(),js引擎在编译期会认为你在执行一个函数声明,会报错. 前面加上运算符只是为让引擎把后面的function(){}语句当作表达式.

注意:变量的声明一定要加上关键字var,尽量在闭包或函数的头部定义要用到的局部变量,函数也是如此,先定义,再调用,这样代码可维护和可读性将大大增强。

2、对象私有的属性和方法:

javascript中又一个众所周知,骂声不绝的鸡肋便是对象缺乏私有的属性和方法,下面是一个简单的私有函数的定义。

function S(){
var mythis = this
mythis.name = “wzh”;
var salary=function(){
return “100”
}();
}
var son = new S();

这里再放一个对象字面量继承的函数,写的很好,很精辟:

var snoopywzh_o = {
name:”wzh”,
age:function(){
alert(‘26’)
}
}
var inherit = function(o){
var f=function(){};
f.prototype=o;
return new f();
}
var snoopywzh = inherit(snoopywzh_o); //这样snoopywzh就可以直接访问snoopywzh_o内的所有属性和方法了
alert(snoopywzh.name); //wzh

3、循环中的length属性:

数组有length属性,字符串也有length属性,我们经常看到这样的代码:
for(var i=0;i<$(“div”).length;i++){
//do something
}
这样会造成每次循环都去查找一遍DOM元素中div的长度,相当影响效率,正确的做法是:
var div_length = $(“div”).length
for(var i=0;i<div_length ;i++){
//do something
}
同样对于长数组JSON对象等也应该如此。

3、尽量避免使用eval和with:
在编写日常javascript的时候应该尽量避免编写eval语句和with语句。例如下面的代码:
snoopywzh={}
var prop = “myname”;
eval(“snoopywzh.”+prop+”=’wzh’ “);
完全可以改写为:
snoopywzh={}
var prop = “myname”;
snoopywzh[prop]=’wzh’;
有权威机构认证,javascript中的eval将消耗更多的资源。
同样with语句也会消耗更多的资源,不要使用他:
snoopywzh={
name:’wzh’,
sex:function(){
alert(‘男’);
}
}
with(snoopywzh){
name=’wzh2’;
sex();
}

4、3种条件判断的讨论:
我们编写javascript脚本通常需要根据变量的不同而做出不同的判断和执行不同的语句,而条件判断的消耗其实是比较大的,我们应该尽量精简判断的次数,比如要判断x从0-9的整数,可以这么写:
if(x===0) { //do something }
else if(x===1) { //do something }
else if(x===2) { //do something }
… …
else if(x===8) { //do something }
else { //do something }
这样如果X为9,则需要杯具的判断9次,因为else是不做判断的,而就算x为5,也需要判断5次。
如果我们把代码稍微修改一下:
if(x<5){
if(x===0) { //do something }
else if(x===1) { //do something }

else { //do something } //此时X为4
}
else{

else { //do something } //此时X为4
}
这样如果从x为5以后都会显著的减少判断的次数,,以上只是一个小例子,具体要根据X的命中率来进行编写,整个判断的流程会提高30%左右。当然如果是很多这样的判断我还是推荐switch case,很多浏览器已经为switch语句做了优化,但是在使用时还需注意2点,将命中率高的选项放在考前,并且每句case语句后记得加上break;
最后一种判断方法是数组法,例如上面的判断可以改写为:
var my_array = [0,1,2,3 … … 9]
if(my_array[x]===x) { //do something }
这种方法有几个局限性,第一个是X必须为比较小的整数或连续整数。第二个是X的可能性值比较大,应该在10个以上,第三点是判断通过以后执行的函数必须有规律可行。
总结一下,当条件不复杂,比较小时可直接用if else
如果判断条件很多,又不是连续数字或者没规律可循的,请选用switch case,切记别忘加上break;
数组法有很多局限性,当都满足时可以使用数组法。

5、多个方法不同地方调用享用一个变量:
例如有这样的情况,可能有多个方法需要不同的地方调用,但是我们又不希望使用全局变量,可以这么写:
var snoopy= function(){
var name=”wzh”;
return {
cardID:function(){
alert(“my card id is”+name)
},
companyID:function(){
alert(“my company id is”+name)
}
}
}();
就可以直接调用:
snoopy.cardID();
snoopy.companyID();

6、多个参数传参:
当一个函数需要传递多个参数时,建议将参数写成对象传递,这样即可以初始化一些参数,又可以在传递时候不必根据顺序选择性的传递参数。
例如: //以下例子需调用JQUERY
var snoopy = {
name:”wzh”;
sex:”male”,
age:function(){alert(“27”);}
}
function person_info(){
var settings = $.extend(
{
name:”snoopy”,
sex:”female”;
age:”27”
},arguments[0]||{}
)
//do something
}
person_info(snoopy); //调用函数,然后就可以直接使用settings.name来使用参数了

6、给数组最后插入一个值:
var myarray = [1,2,3,4]
myarray[myarray.length] = 5; //[1,2,3,4,5]

7、数组的常用方法splice:
var myarray = [0,1,2,3,4,5]
删除:var remove = myarray.splice(0,2) //remove的值为[0,1],myarray的值为[2,3,4,5]
插入:var insert = myarray.splice(3,0,88,77,66) //insert的值为undefined , myarray的值为[0,1,2,88,77,66,3,4,5]
替换:var exchange = myarray.splice(3,2,88,77,66) //exchange 的值为[3,4] ,myarray的值为[0,1,2,88,77,66,5]

8、比较2个日期的相差的天数:
var m_second1 = Date.parse(dateobject);
var m_second2 = dateobject.getTime();
以上2种情况返回的值是相同的。
这个函数可以返回日期对象的相对于1970.1.1的经过的毫秒数,两个毫秒数相减,就可以计算出2个日期相差的天数或者小时数了

9、return this连续调用自定义对象方法:
例如有这样一个DOM元素:


脚本如下:
Object.prototype.setWidth = function(w){
this.style.width = w+’px’;
return this;
}
Object.prototype.setHeight = function(h){
this.style.height = h+’px’;
return this;
}
Object.prototype.setBgColor = function(c){
this.style.backgroundColor = c;
return this;
}
document.getElementById(“snoopy”).setWidth(80).setHeight(100).setBgColor(“#f00”);
运行这段脚本之后,可以将div设置为宽80px,高100px,背景色为红色的div,可以就像定义连续技一样自定义多个方法以供调用。

10、建议尽量不要使用String对象、Boolean对象和Number对象:
虽然JS可以存在new String或是Boolean和Number,但是建议尽量不要使用它们,使用他们会有不必要的麻烦。并且typeof 和 instanceof得出的结果也不相同。

先以String对象为例:
var s1 = “aaa”;
s1.color = “xxx”;
alert(s1.color); //undefined

var s2 = new String(“aaa”);
s2.color = “xxx”;
alert(s2.color); //xxx

以Boolean对象为例:
var bl = new Boolean(“false”);
var r = bl && true;
alert(bl); //true

var bl2 = false;
var r2 = bl2 && true;
alert(bl2); //false

11、解决单纯原型模式下共享属性的问题。
首先我们先看如下的代码:
function Me(){}
Me.prototype = {
constructor:Me,
name:”snooopy”,
age:”26”,
lover_color:[“red”,”blue”]
}
var wzh1 = new Me();
var wzh2 = new Me();
var wzh3 = new Me();
wzh1.age = “27”;
wzh2.age = “28”;
alert(wzh1.age); //27
alert(wzh2.age); //28
alert(wzh3.age); //26
注意这里,我们单独为wzh1和wzh2这两个实例设置了age属性,他们是互相不冲突的,并且不会去修改原型上的age属性值。
接下来我们为每个实例单独定义lover_color属性。
wzh1.lover_color.push(“green”);
alert(wzh1.lover_color); //red,blue,green
alert(wzh2.lover_color); //red,blue,green
alert(wzh3.lover_color); //red,blue,green
wzh2.lover_color.push(“orange”);
alert(wzh1.lover_color); //red,blue,green,orange
alert(wzh2.lover_color); //red,blue,green,orange
alert(wzh3.lover_color); //red,blue,green,orange
注意:这里我先修改了wzh1的lover_color属性,再修改了wzh2的lover_color属性,发现牵一发而动全身了,这就是数组引用复制的结果,所以要除掉这个令人郁闷的错误,需要将原型模式和构造函数模式结合起来。
注意:可能有很多喜欢使用构造函数来创建原型,例如:
function Me(){
this.name = “snoopy”;
this.age = “26”;
this.lover_color = [“red”,”blue”]
this.say= function(){
alert(this.name)
}
}
var wzh1 = new Me();
var wzh2 = new Me();
wzh1.lover_color.push(“green”);
alert(wzh1.lover_color); //red,blue,green
alert(wzh2.lover_color); //red,blue
虽然这样wzh1和wzh2的lover_color属性没有冲突,但是如果需要用到共享的一些方法,例如say方法,这样写法会造成效率地下,wzh1和wzh2各构造一个say函数,所以最好还是将构造函数和单纯原型结合起来。
将共享的一些属性和方法放在单纯原型中,将以后可能会更改的一些属性和方法放在构造函数中。
例如:
function Me(){
this.age = “26”;
this.lover_color = [“red”,”blue”]
}
Me.prototype = {
constructor:Me,
name:”snooopy”,
say: function(){
alert(this.name)
}
}

11、关于setTimeout()和setInterval()函数
大家肯定都非常熟悉setTimeout()和setInterval()这两个函数了,都是用来做延迟动作,重复,间隔调用或轮询的。功能一摸一样,区别在于前者主要用来延迟操作,而后者用来间隔调用和轮询,我们先看下代码:
var a = function(){
alert(“gogogo!”)
}
var go1 = setTimeout(function(){a();},3000); //过3000毫秒后执行一次alert(“gogogo!”)
var go2 = setInterval(function(){a();},3000); //每隔3000毫秒后执行一次alert(“gogogo!”)
不过看到网上有很多人这么写:
var go3 = setTimeout(“a()”,3000); //过3000毫秒后执行一次alert(“gogogo!”)
var go4 = setInterval(“a()”,3000); //每隔3000毫秒后执行一次alert(“gogogo!”)
这样写虽然也能够完成功能,但是相当于每次都eval()执行一下字符串,效率较低,所以还是建议像上面那么写!

12、函数链式调用
var a = function(p){
alert(p);
return arguments.callee;
}(‘xx’)(‘yy’);
不解释!

13、遍历某一节点的所有属性
可以利用element.attributes属性来遍历,这个属性是一个数组,我们可以这样取到该节点的属性名和属性值:
element.attributes[i].nodeName; //属性名
element.attributes[i].nodeValue; //属性值,文本值
element.attributes.length //属性个数,数组长度
然后就可以遍历拉,不解释!

13、克隆数组
var a = [1];
var b=a.concat();
a[0]=100;
alert(b[0]); //1

14、冒泡绑定clikc事件
例如有这样的代码:

  • 1
  • 1
  • 1

  • 1


  • 我们需要为每个li绑定click事件做出不同的事件。
    我们完全可以只绑定ul,然后根据event.target.id来进行switch case选择,这样可以提高效率。

    15、setTimeout 的装X写法
    var x = function(a,b){alert(a+b)}
    setTimeout(x,1000,1,2)
    会弹出alert(3)