自定义函数
JS中有两种方法定义函数:
使用function关键字定义函数
function test(){
alert('this is a test!');
return 1;
}
test(); // 执行函数
使用js中的函数构造器(Function())定义函数
var func=new Function('a', 'b', 'return a+b');
var func=function(a,b){return a+b;};
以上两种是等价的,尽量避免使用new关键字
注意:
- 函数名称不要包含特殊字符
- 函数名称最好含义明确
- 函数名称最好遵循驼峰标记法或者下划线法
- 函数名称严格区分大小写
- 函数名称如果相同会产生覆盖
- 函数可以有参数,也可以没有参数
- 函数可以通过return加返回值,如果没有return默认返回的是undefined
- 函数不调用不执行
函数参数问题:
- 函数可以有参数,也可以没有参数,如果在函数调用的时候没有传参,默认是undefined
- 在函数调用的时候,如果所给参数超出所需参数,将会忽略后面的参数
- js中不支持默认参数,可以通过arguments对象来实现默认参数的效果
- 可以通过arguments对象实现可变参数的函数
- 通过值传递参数在函数体内对其变量做修改不会影响变量本身
- 通过对象传递参数在函数体内对变量更改会影响变量本身
可以使用以下的方法来实现默认参数:
// 方法1
function calc(x, y){
x = x||1;
y = y||2;
}
// 方法2
function calc(x, y){
if(x===undefined){
x=0;
}
y=y===undefined?0:y; // 三元运算符
return x+y
}
// 方法3 使用arguments对象
function calc(x,y){
x=arguments[0]?arguments[0]:0;
y=arguments[1]?arguments[1]:0;
return x+y;
}
// 使用arguments对任意个参数求和
function calc(){
var paramsNum = arguments.length;
var sum = 0;
for(var i=0;i<paramsNum;++i){
sum+=arguments[i];
}
return sum;
}
变量的作用域:
- 在函数体内声明的变量,仅在函数体内可以使用 > 局部变量
- 在函数体外生命的变量,在函数声明到脚本结束,都可以使用 > 全局变量
- 尽量控制全局变量的数量
- 最好总是使用var语句来声明变量
- 通过值传递参数在函数体内对其变量做修改不会影响变量本身
- 通过对象传递参数在函数体内对变量更改会影响变量本身
- 在函数体内如果直接定义变量 不加var关键字,默认就是全局变量
function test(){
a = 15; // 在函数体内,没有使用var关键字,a就是全局变量
return a;
}
alert(test()); // 弹出15
alert(a) // 这个时候a的值是15
function test(){
var a = 15; // 在函数体内,使用var关键字,此时是局部变量
return a;
}
alert(test()); // 弹出15
alert(a) // 会报错,提示a未定义
JS中的全局函数
parseInt()
当参数radix的值为0时,或者没有这个参数时,parseInt()会根据string来判断数字的基数,如果设置了radix的值,将会转换成对应的进制。
基数规则:
- 字符串以0开始的时候,旧的浏览器默认使用八进制作为基数,ECMAScript5,默认的是十进制的基数
- 如果string以0x开头,将会被解析成十六进制。
- 如果string以1-9开始,将会被解析成十进制。
- 字符串以合法字符开头,截取合法的字符。
- 开头和结尾允许有空格。
- 如果字符串的第一个字符不能被转换成数字,parseInt() 将会返回NaN。
parseFloat(): 转换成浮点型的值
isFinite(value): 检测是否是无穷值
isNaN(value): 检测是否是NaN
encodeURI(uri): 将字符串编码为uri
decodeURI(uri): 解码某个uri
encodeURIComponent(uri): 将字符串编码为uri组件
decodeURIComponent(uri): 解码某个uri的组件
escape(): 对字符串进行编码
unescape(): 解码有escape()编码的字符串
eval(): 将js字符串当做脚本运行
Number(object): 将对象的值转换成数字
String(): 将对象的值转换成字符串
匿名函数
function(){return 5; };
函数表达式可以存储在一个变量中,变量也可以作为一个函数使用
可以将匿名函数作为参数传递给其他的函数,接收方的函数可以通过所传递的函数完成某些功能
可以通过将匿名函数来限制性一些一次性的任务
几种特殊类型的函数
- 函数也是数据
- 回调函数 将函数当做变量传递给一个函数
- 自调函数
(function(a, b){
alert(a+b);
})(3,5);
-
内部(私有)函数
在函数体内定义的函数 -
重写自己的函数
实现类似于初始化的函数
function a(){
alert('aaa');
a = function(){
alert('bbb');
}
}
a();
a();
var a=function(){
function setUp(){
var setup='初始化';
}
function doWhat(){
alert('要执行的操作');
}
setUp();
return doWhat;
}();
a();
- 闭包
词法作用域:
function f1(){
var a=12;
return f2();
}
function f2(){
return a;
}
alert(f1());
报错:a未定义, 因为不能共享作用域:
闭包的一些例子;
function f(){
var a=100;
return function(){
return a;
}
}
var test=f();
alert(test());
实现访问函数内部的值;
var n;
function f(){
var a=200;
n=function(){
return a;
};
}
f();
alert(n());
function(){
var n=function(){
return param;
}
return n;
}
var test=f(100);
alert(test());
function f1(){
var n=1;
test=function(){
n+=1;
};
function f2(){
alert(n);
}
return f2;
}
var res=f1();
alert(res());
rest();
alert(res());
var setValue,getValue;
(function(){
var n=0;
getValue=function(){
return n;
};
setValue=function(x){
n=x;
}
})();
alert(getValue());
alert(setValue(100));
// 实现迭代器;
function test(x){
var i=0;
return function(){
return x[i++];
};
}
var next=test([1,2,3,4,5]);
alert(next());
alert(next());
alert(next());
alert(next());
alert(next());
function f(){
var a=[];
var i;
for(i=0;i<3;i++){
a[i] = function(){
return i;
}
}
return a;
}
var test=f();
alert(test[0]());
alert(test[1]());
alert(test[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 test=f();
alert(test[0]());
alert(test[1]());
alert(test[2]());
// 下面是另外一种方法
function(){
function(){
return function(){
return x;
}
}
var a=[];
var i;
for(i=0;i<3;i++){
a[i]=test(i);
}
return a;
}
var res = f();
alert(res[0]());
alert(res[1]());
alert(res[2]());
使用闭包缺点:
闭包会是的函数中的变量都保存在内存中,内存小号很大,所以不能滥用
否则会造成网页的性能问题,在ie中,肯能导致内存泄漏,尽量在退出函数之前,将不用的变量删除。