js 函数与’+’

在查看bs源码是看见几乎所有的function都是+function ($) {?//todo}(jQuery);的格式,之前也有遇见‘+’这个函数命名情况,故研究了一下这个问题,不看不知道,一看才知道这个坑好深,此文为所收集资料的整合,加上自己的一些感悟,文末有一些资料的链接,感谢热心回答我问他的coder们!

一、首先js声明函数的语法为:

function fnA(){ //todo } //定义函数
var B = function(){ //todo } //定义匿名函数

因此在调用自定义函数的时候会采用 B(); 这样,其中B为一个表达式,() 是一种函数调用运算符,那么我们在调用匿名函数时将B换成其他可以表达该函数的表达式就可以调用这个函数,而使用括号就刚好可以将括号以内的值变为一个表达式

则可以通过下面的方式实现匿名函数的自调用:

(function(){ //todo})()

(function(){ //todo}())

上述两种方法效果一样

所以由上我们可知,只要将匿名函数声明转为表达式,那么,就可以实现匿名函数的自调用。

因此,若你不在意函数的返回结果的话,赋值,运算,逗号等操作符都能告诉读者,这个不是函数声明,而是一个表达式,所以以下三种都可以实现函数的自调用,也称为IIFE:立即调用的函数表达式。

+function(){ // todo}()

!function(){?// todo}()

-function(){?// todo}()

同理,既然是表达式,那么就可以进行相应的运算了

例如:alert(+function(){return 5}() ??+function(){ return 10}())的结果是15

 

二、再来,一般来说在使用jquery时,会使用页面载入后执行的函数

$(document).ready(function(){?//todo}),或简写为$(function){?//todo}

但是,在使用多方的js库文件时,为避免命名空间的冲突,也就是避免除去jquery以外其他的库文件也使用了$符号,所以使用下面的方法来声明函数

(function($){ //todo ?})(jquery);//jquery为实参,$为形参

 

三、最后,当我满以为这样就大功告成的时候,发现,绑定事件时出了问题

 

(function($){

//method1
$(‘.nav’).click(function(){
console.log(‘method1’);
})

//method2
$(document).on(‘click’, ‘.nav’, function (e) {
console.log(‘method2’);
})
//method3
$(document).delegate(‘.nav’, ‘click’, function() {
console.log(‘method3’);
});
//method4
$(function(){
$(‘.nav’).click(function(){
console.log(‘method4’);
})
})

})(jQuery);

上述方法中,method1是无法正常执行的,原因是(function($){ //todo ?})(jquery)不等同与$(function){ //todo},(function($){ //todo ?})(jquery)仅仅是函数的声明,即method1会在dom加载完之前执行,而$(‘.nav’).click(function(){})是为dom节点绑定事件,所以当dom节点都还没加载完时,绑定的事件是无效的。

解决上述问题的办法有三种:

1.由于页面是由上至下加载的,所以可以通过改变js加载的位置,将其放在</body>上面,即<body>的最下面,而且将js放在<body>最下面还有个好处是,先让用户看到页面,再加载事件,避免js文件过大,影响加载的速度

2.在文档加载完时绑定事件,原生js的onload事件,或jquery的ready()事件,如method4

3.使用事件委托,如method2,method3

参考资料:

http://my.oschina.net/lzh1104/blog/160668

http://benalman.com/news/2010/11/immediately-invoked-function-expression/

http://swordair.com/function-and-exclamation-mark/

发表评论

电子邮件地址不会被公开。