自执行函数和匿名函数


 

 

在很多JS库中都能看到下面的代码:

function(){ //所有库代码代码
}();

 

这样写的一个目的是——封装。

JavaScript并不是面向对象的,所以它不支持封装。但是在不支持封装的语言里同样可以实现封装。而实现的方法就是匿名函数或者自执行函数,其实自执行函数是特殊的匿名函数。在JS中类是通过函数来模拟的,其实很难理解,但是理解了也是比较轻松的,都知道在C#/Java等语言中,类是创建对象的模板,也是属性和方法的集合,类中中可以定义多个方法,既然在JS中可以通过函数来模拟,那么函数中自然也就可以定义新的函数,或者说内部函数,如下面的就是一个类:

//定义
function F(x) { this.x = x; function double(x){return x*x;} this.getDoubleX = function(){ return double(this.x); } } //使用
f = new F(12); alert(f.getDoubleX());

 

函数F相当于一个构造函数,而函数里面的其他定义都是函数私有的外部无法访问,例如double函数。这样就变相实现了私有方法。其他打上“this.”前缀的成员相当于公开成员,外部可以访问。前面的博客中我写过如何写一个可以复用的JS文件,这个就采用的是自执行函数,现在给一个将图片翻转360度的,这个函数就是给windows增加了一个新的对象或者命名空间,这个命名空间用来存放我自己定义的东东:

 

(function (wx) { var T$ = function (id) { return document.getElementById(id); } var ua = navigator.userAgent, isIE = /msie/i.test(ua) && !window.opera; var i = 0, sinDeg = 0, cosDeg = 0, timer = null; var rotate = function (target, degree) { target = T$(target); var orginW = target.clientWidth, orginH = target.clientHeight; clearInterval(timer); function run(angle) { if (isIE) { // IE
                    cosDeg = Math.cos(angle * Math.PI / 180); sinDeg = Math.sin(angle * Math.PI / 180); with (target.filters.item(0)) { M11 = M22 = cosDeg; M12 = -(M21 = sinDeg); } target.style.top = (orginH - target.offsetHeight) / 2 + 'px'; target.style.left = (orginW - target.offsetWidth) / 2 + 'px'; } else if (target.style.MozTransform !== undefined) {  // Mozilla
                    target.style.MozTransform = 'rotate(' + angle + 'deg)'; } else if (target.style.OTransform !== undefined) {   // Opera
                    target.style.OTransform = 'rotate(' + angle + 'deg)'; } else if (target.style.webkitTransform !== undefined) { // Chrome Safari
                    target.style.webkitTransform = 'rotate(' + angle + 'deg)'; } else { target.style.transform = "rotate(" + angle + "deg)"; } } timer = setInterval(function () { i += 10; run(i); if (i > degree - 1) { i = 0; clearInterval(timer); } }, 10); } wx.liuyu = {}; wx.liuyu.rotate = rotate; // windows.rotate = rotate;
 }) (window);

 

调用

window.onload = function () {         document.getElementById('demo').onclick = function () {             window.liuyu.rotate('demo', 360); } }

 其实还可以采用下面这种方式,这种方式给左边的变量返回了一个对象,记住这个不是函数的定义,而是可以直接执行的:

  var Img=function () { var T$ = function (id) { return document.getElementById(id); } var ua = navigator.userAgent, isIE = /msie/i.test(ua) && !window.opera; var i = 0, sinDeg = 0, cosDeg = 0, timer = null; var rotate = function (target, degree) { target = T$(target); var orginW = target.clientWidth, orginH = target.clientHeight; clearInterval(timer); function run(angle) { if (isIE) { // IE
                    cosDeg = Math.cos(angle * Math.PI / 180); sinDeg = Math.sin(angle * Math.PI / 180); with (target.filters.item(0)) { M11 = M22 = cosDeg; M12 = -(M21 = sinDeg); } target.style.top = (orginH - target.offsetHeight) / 2 + 'px'; target.style.left = (orginW - target.offsetWidth) / 2 + 'px'; } else if (target.style.MozTransform !== undefined) {  // Mozilla
                    target.style.MozTransform = 'rotate(' + angle + 'deg)'; } else if (target.style.OTransform !== undefined) {   // Opera
                    target.style.OTransform = 'rotate(' + angle + 'deg)'; } else if (target.style.webkitTransform !== undefined) { // Chrome Safari
                    target.style.webkitTransform = 'rotate(' + angle + 'deg)'; } else { target.style.transform = "rotate(" + angle + "deg)"; } } timer = setInterval(function () { i += 10; run(i); if (i > degree - 1) { i = 0; clearInterval(timer); } }, 10); } return {"rotate":rotate}; }(); window.onload = function () { document.getElementById('demo').onclick = function () { Img.rotate('demo', 360); } }
 
对于上面的这个方式,有些人可能不太明白,我们可以这样理解:
  var Img=function () { var T$ = function (id) { return document.getElementById(id); } var ua = navigator.userAgent, isIE = /msie/i.test(ua) && !window.opera; var i = 0, sinDeg = 0, cosDeg = 0, timer = null; var rotate = function (target, degree) { target = T$(target); var orginW = target.clientWidth, orginH = target.clientHeight; clearInterval(timer); function run(angle) { if (isIE) { // IE
                    cosDeg = Math.cos(angle * Math.PI / 180); sinDeg = Math.sin(angle * Math.PI / 180); with (target.filters.item(0)) { M11 = M22 = cosDeg; M12 = -(M21 = sinDeg); } target.style.top = (orginH - target.offsetHeight) / 2 + 'px'; target.style.left = (orginW - target.offsetWidth) / 2 + 'px'; } else if (target.style.MozTransform !== undefined) {  // Mozilla
                    target.style.MozTransform = 'rotate(' + angle + 'deg)'; } else if (target.style.OTransform !== undefined) {   // Opera
                    target.style.OTransform = 'rotate(' + angle + 'deg)'; } else if (target.style.webkitTransform !== undefined) { // Chrome Safari
                    target.style.webkitTransform = 'rotate(' + angle + 'deg)'; } else { target.style.transform = "rotate(" + angle + "deg)"; } } timer = setInterval(function () { i += 10; run(i); if (i > degree - 1) { i = 0; clearInterval(timer); } }, 10); } return {"rotate":rotate}; } window.onload = function () { //Img.rotate('demo', 360);
        document.getElementById('demo').onclick = function () { var xRotate = Img(); xRotate.rotate('demo', 360); } } </script>

 

这两个的微小区别其实跟JS的编译和运行两个阶段有关,从下面的例子可以看出:
 
function a(){ alert("a") } var b = function(){ alert("b") } 

它们俩有何不同呢?前者为函数声明,后者为函数表达式。函数声明作为一种声明,当然会在预编译阶级有所动作(声明提前),而函数表达式则不会。另一个区别是,函数声明不能直接加一对括号让它们执行。第三个区别,表达式还可以继续细分,表达式是由常量,变量,操作符,函数等组合而成,计算以后返回一个结果值,至少也会返回一个undefined。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM