函数部分分为几个部分:
1.本篇文章介绍函数定义的方法
http://blog.csdn.net/github_34514750/article/details/51049908
2.函数内部的对象
http://blog.csdn.net/github_34514750/article/details/51336321
3.函数属性和方法
http://blog.csdn.net/github_34514750/article/details/51336518
4.IIFE立即调用函数表达式
1.立即调用的函数表达式Immediately-Invoked Function Expression (IIFE)
函数的正常调用
函数function foo(){}或者var foo = function(){},调用时,你都需要在后面加上一对圆括号,像这样foo()。
立即调用的函数表达式
立即调用的函数表达式如果没有引用的话(没有赋值给变量),是在代码执行阶段这个的function就会被创建,并且立即执行,然后自动销毁。(因为是函数表达式,不在VO中)
//立即调用的几种形式
var foo = function(){}();
//这两种模式都可以被用来立即调用一个函数表达式,利用函数的执行来创造私有变量
(function(){/* code */}());//Crockford recommends this one,括号内的表达式代表函数立即调用表达式
(function(){/* code */})();//But this one works just as well,括号内的表达式代表函数表达式
//下面一个立即执行的函数,周围的括号不是必须的,因为函数已经处在表达式的位置
var foo = {
bar: function (x) {
return x % 2 != 0 ? 'yes' : 'no';
}(1)
};
alert(foo.bar); // 'yes'--foo.bar是一个字符串而不是一个函数,这里的函数仅仅用来根据条件参数初始化这个属性——它创建后并立即调用
function (){}();和function foo(){ }();–都不是立即调用的函数表达式,且都会报错
原因:因为圆括号放在一个函数表达式后面指明了这是一个被调用的函数;但是有关键字function,解释器会将它看做是函数声明,若在一个声明后面则意味着只是一个分组操作符。
比如:
alert(foo); // 函数
function foo(){
alert(x);
}(1);
foo(10); // 这才是一个真正的函数调用,结果是10
// 1只是分组操作符,不是函数调用,其实相当于下边这段代码
// 下面的声明的时候产生了2个对象:一个函数声明,一个带有1的分组操作符
function foo(){
alert(x);
}
// 一份分组操作符,包含一个表达式1
(1);
解决:将函数声明包裹在圆括号里来告诉语法分析器去当成一个函数表达式解析,这样才对(function foo(){ })()
保存闭包的状态
一个立即调用的函数表达式可以用来锁定值并且有效的保存此时的状态
闭包:一个函数内的函数可以访问外部函数作用域的变量
//i没有被锁定,相反的,每个链接,当被点击时(循环已经被很好的执行完毕),因此会弹出所有元素的总数,因为这是 `i` 此时的真实值。
var elems = document.getElementsByTagName("a");
for(var i = 0,len = elems.length;i < len;i++) {
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + i)
},false);
}
// 而像下面这样改写,便可以了,因为在IIFE里,`i`值被锁定在了`lockedInIndex`里。
// 在循环结束执行时,尽管`i`值的数值是所有元素的总和,但每一次函数表达式被调用时,
// IIFE 里的 `lockedInIndex` 值都是`i`传给它的值,所以当链接被点击时,正确的值被弹出。
var elems = document.getElementsByTagName("a");
for(var i = 0,len = elems.length;i < len;i++) {
(function(lockedInIndex){
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + lockedInIndex);
},false);
})(i);
}
//你同样可以像下面这样使用IIFE,仅仅只用括号包括点击处理函数,并不包含整个`addEventListener`。
//无论用哪种方式,这两个例子都可以用IIFE将值锁定,不过我发现前面一个例子更可读
var elems = document.getElementsByTagName("a");
for(var i = 0,len = elems.length;i < len;i++) {
elems[i].addEventListener('click',(function(lockedInIndex){
return function(e) {
e.preventDefault();
alert('I am link #' + lockedInIndex);
};
}(i),false);
}