JavaScript函数

自定义函数

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关键字

注意:

  1. 函数名称不要包含特殊字符
  2. 函数名称最好含义明确
  3. 函数名称最好遵循驼峰标记法或者下划线法
  4. 函数名称严格区分大小写
  5. 函数名称如果相同会产生覆盖
  6. 函数可以有参数,也可以没有参数
  7. 函数可以通过return加返回值,如果没有return默认返回的是undefined
  8. 函数不调用不执行

函数参数问题:

  1. 函数可以有参数,也可以没有参数,如果在函数调用的时候没有传参,默认是undefined
  2. 在函数调用的时候,如果所给参数超出所需参数,将会忽略后面的参数
  3. js中不支持默认参数,可以通过arguments对象来实现默认参数的效果
  4. 可以通过arguments对象实现可变参数的函数
  5. 通过值传递参数在函数体内对其变量做修改不会影响变量本身
  6. 通过对象传递参数在函数体内对变量更改会影响变量本身

可以使用以下的方法来实现默认参数:

// 方法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;
}

变量的作用域:

  1. 在函数体内声明的变量,仅在函数体内可以使用 > 局部变量
  2. 在函数体外生命的变量,在函数声明到脚本结束,都可以使用 > 全局变量
  3. 尽量控制全局变量的数量
  4. 最好总是使用var语句来声明变量
  5. 通过值传递参数在函数体内对其变量做修改不会影响变量本身
  6. 通过对象传递参数在函数体内对变量更改会影响变量本身
  7. 在函数体内如果直接定义变量 不加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的值,将会转换成对应的进制。

基数规则:

  1. 字符串以0开始的时候,旧的浏览器默认使用八进制作为基数,ECMAScript5,默认的是十进制的基数
  2. 如果string以0x开头,将会被解析成十六进制。
  3. 如果string以1-9开始,将会被解析成十进制。
  4. 字符串以合法字符开头,截取合法的字符。
  5. 开头和结尾允许有空格。
  6. 如果字符串的第一个字符不能被转换成数字,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中,肯能导致内存泄漏,尽量在退出函数之前,将不用的变量删除。