?
这篇记录函数的用法
标准函数定义:
? ? function?sum(a,?b)?{?
var?c?=?a?+?b;?
return?c;
}
其中a和b叫做函数的参数,函数体内return?c是将c作为返回值(如果没有显式的return,默认返回undefined),虽然函数只声明了两个参数,实际上调用的时候可以传入任意数量的参数,比如:sum(1,2,3,4,5),每个函数都会默认创建一个arguments变量,类似一个数组,可通过下标访问所有的参数
?
预定义的函数:
下面这些函数都是黑盒,无法查看内部实现代码
parseInt()
尝试把任意类型转换成整数,如果转换失败,返回NaN
一些示例:
parseInt('123')?>>>123
parseInt('abc123')?>>>NaN
parseInt('1abc23')?>>>1
parseInt('123abc')?>>>123
?
第二个参数表示进制
parseInt('FF',?10)?>>>NaN
parseInt('FF',?16)?>>>255?//十六进制
parseInt('0377',?10)?>>>377
parseInt('0377',?8)?>>>255?//八进制
?
对于0开头的字符串,parseInt会默认把它当成8进制转换,如:
parseInt('0377')?>>>255
对于0x开头的字符串,parseInt会默认把它当成十六进制进行转换,如:
parseInt('0x377')?>>>887
?
parseFloat()
尝试把参数转换成小数,只有1个参数,转换失败会返回NaN
区别:
parseInt("1.9")>>>1????parseFloat("1.9")>>>9
parseInt("1e2")>>>1 ???parseFloat("1e2")>>>100
parseFloat('1.23abc.00')>>>1.23
parseFloat('a.bc1.23')?>>>NaN
?
isNaN()
判断参数是不是数字,如果不是数字,返回false,可以用来判断parseInt和parseFloat是否转换成功。
isNaN(NaN)?>>>true
isNaN(123)?>>>false
isNaN(1.23)?>>>false
isNaN(parseInt('abc123'))?>>>true
这个函数会尝试转换参数:
isNaN('1.23')?>>>false
isNaN('a1.23')?>>>true
isNaN('1px')>>>true //严格匹配,parseInt和parseFloat可以转换,但isNaN不认为它是个数字
因为NaN==NaN返回false,所以这个函数非常有用。
?
isFinite()
判断参数是一个数字,而不是Infinity或NaN
isFinite(Infinity)?>>>false
与isNaN类似,它也会尝试转换字符串
isFinite("0")?>>>true
?
?
encodeURI()?/encodeURIComponent()?,decodeURI()?/decodeURIComponent()?
encodeURI会把参数当作一个完整的URI字符串处理
encodeURIComponent()会把参数当作URI的一部分,比如查询部分,所以所有的特殊字符都会被encode。
?
eval()
将参数当作一段javascript执行,不建议使用,会有性能和安全问题
?
?
?
变量作用域
在js中没有块作用域(不同于java),只有函数作用域和全局作用域
在函数内部定义的变量只有函数内或此函数的私有函数能访问,外部不能访问,如:
? ? var?global?=?1;
? ? function?f()?{?
var?local?=?2;?
global++;?
return?global;
}
global是全局的,在f内也可以访问,但是local是在f内定义的,不能被外部访问
?
注意,如果不小心丢掉了var关键字,local会被分配为全局变量
?
?
函数内的变量声明会覆盖全局声明:
var?a?=?123;
function?f()?{?
alert(a);?//undefined
var?a?=?1;?
alert(a);?//1
}?
? ? f();?
?
?
?
?
函数也是数据(变量),两种定义方式:
? ? function?f(){return?1;} //函数声明
var?f?=?function(){return?1;} //函数表达式
typeof?f>>>"function"
完全可以把函数当作普通变量处理,让一个新变量指向它,当作参数传递,当作返回值,或者干脆delete?f
?
匿名函数:
~function(a){alert(a)}(1);//定义一个匿名函数并马上执行它
?
私有函数
? ? function?a(param)?{?
function?b(theinput)?{?
return?theinput?*?2;?
};?
return?'The?result?is?'?+?b(param);
};
其中b就是一个private?function
或者用函数表达式的方式:
? ? var?a?=?function(param)?{?
? var?b?=?function(theinput)?{?
return?theinput?*?2;?
};?
return?'The?result?is?'?+?b(param);
};
?
?
综合应用,重写自己:
function?a()?{?
alert('A!');?
a?=?function(){?
alert('B!');?
};
? ? }
只有第一次执行a时才会alert('A!');?适合做一些只做一次的初始化工作
?
或者:
var?a?=?function()?{?
function?someSetup(){?
var?setup?=?'done';?//马上会被执行,因为函数最后有一对小括号
}?
function?actualWork()?{?
alert('Worky-worky');?
}?
someSetup();?
return?actualWork;
? ? }();
?
闭包
关于闭包的概念,网上有很多介绍的很多,在这不解释意义了,来几个例子,加深印象:
1、
function?f(){?
var?b?=?"b";?
return?function(){?
return?b;?
}
? ? }
想在外部访问f的内部变量b,可以:
var?n=f();
var?b=n();
或者:
var?n;
function?f(){?
var?b?=?"b";?
n?=?function(){?//n在外部声明
return?b;?
}
? ? }
?
2、
function?f(arg)?{?
var?n?=?function(){?
return?arg;?
};?
arg++;?
return?n;
? ? }
var?m?=?f(123);
m();//结果是124
?
3、
function?f()?{?
var?a?=?[];?
var?i;?
for(i?=?0;?i?<?3;?i++)?{?
a[i]?=?function(){?
return?i;?
}?
}?
return?a;
? ? }
var?a?=?f();
a[0]()=3,a[1]()=3,a[2]()=3
修正一下:
function?f()?{?
var?a?=?[];?
var?i;?
for(i?=?0;?i?<?3;?i++)?{?
a[i]?=?(function(x){?
return?function(){?
return?x;?
}?
})(i);?
}?
return?a;
? ? }
var?a?=?f();
a[0]()=0,a[1]()=1,a[2]()=2
?
或者:
function f() { function makeClosure(x) { return function(){ return x; } } var a = []; var i; for(i = 0; i < 3; i++) { a[i] = makeClosure(i); } return a; }
?