您的位置:首页 > 其它

自执行函数和匿名函数

2013-12-13 16:02 232 查看
在很多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。

参考: /article/1308019.html
http://www.nowamagic.net/javascript/js_UsageOfAnonymousFunctions.php
/article/6948017.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: