学习笔记,
来源:http://www.cnblogs.com/zuiyirenjian/p/3535126.html
作者:醉意人间
此外,关于自运行函数可参考 http://benalman.com/news/2010/11/immediately-invoked-function-expression/
在JS中,也常常需要复用,将一些常见的操作封装起来,目前看到的很多JS库,比如JQuery就是非常典型的,那么如何在JS中写一个可复用的呢?虽然在JS中有类的这个说法,但是我对这个玩意还是很抵触的,但是存在即合理。JS中的类是通过函数来模拟的,也就是说JS中的函数具有双重角色,用new关键字的将函数视为类,不用new的,它就是一个普普通通的函数。
我们知道,类就是一个数据类型,这个数据类型由属性和方法(函数)组成,如果函数只有属性,没有方法,那么这样的类,一般就单纯的表示为一个数据,增加上一些方法,那么类的功能将会有质的变化。既然在JS中,函数可以表示为类,而类中又有方法,那么在JS中函数内部新定义一个函数,也就不足为怪。
JS中最为强大的内容,我认为除了原型,就是闭包,这里就讨论闭包,闭包其实就是在一个函数内部定义一个新的函数,在执行的时候,会将这个函数返回,也可能是返回一个对象。下面就是一个简单的闭包:
var MathTest = function (x, y) { var x = x; var y = y; var add = function () { return x + y; } return add; }
var x = MathTest(3, 4); alert(x());
在执行的时候MathTest就是内部的add函数,调用MathTest的时候,相当于执行了x+y,这其实并不起卦,可以将add认为是function内部的一个变量,只是这个变量的值是一个函数,内部的函数是可以访问它的上一个级别的数据,所以我们可以得到正确的值。
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 } } ();
调用代码:
Img.rotate('demo', 360);
这个是一个比较复杂的,但是不要怕,这里会牵扯到另外的知识,自执行函数和匿名函数。
所谓匿名函数就是没有名字的函数,形式如下:
function () { }
既然没有名字,那么如何调用呢:
var b=function () { }
b()
可以将匿名函数付给一个变量,这个变量现在就充当了这个函数的名称,但是记住,这个不是名称,我只是这么叫,如果觉得不妥的话,可以认为b现在就是这个匿名函数的代表,在用的时候用b就等同于使用右边的函数。除了这种方式,还有就是自执行函数,形式如下:
(function(){ //代码 })();
自执行函数相当于我们上面两步的结合:
var b=function () { }
b()
自执行函数是非常有用的,可以用它创建命名空间,只要把自己所有的代码都写在这个特殊的函数包装内,在使用的时候只需要用这个奇怪的函数即可,伟大的JQuery就是通过这个奇怪的函数创建了一个$的对象,在这个匿名函数中,往往会定义一个属于自己的命名空间,或者返回一个属于自己的对象,上面的Img对象包含了旋转图片的操作,这操作中,调用了很多匿名函数中定义的其它方法,这些方法都是为Rotate来服务的。那么以后写自己可服用的操作的时候,就可以通过这种做法。
我们见到的操作通常都是返回一个对象,但是也可以放回一个函数,下面的,但是调用的时候,写法有所差异:
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 ; } ();
调用代码:
Img('demo', 360);
这两种方式,根据自己的习惯,我个人倾向前者。