被括号括住的JavaScript函数
在JavaScript经常会看到这样的代码
( function( $ ){ $( ‘body‘ ).css( { ‘background-color‘: ‘#ccc‘ } ); } )( jQuery );
这里的一个JavaScript函数被一个括号括了起来, 然后后面紧跟着一个括号,这种奇葩的写法在其它如Java、VB、c#、c++、php等流行编程语言中根本见不到。这种写法乍一看是JavaScript特意增加的新奇特性, 其实并不是。 在我们编写任何程序时,时时刻刻在用到与上面代码类似的特性, 只不过是以另一种面貌展示而已。 说穿了这其它只是括号的运用而已。
在小学数据就学习了括号在加减乘除四则运算中可以控制优先级。 (1+1)*3这是一个最简单的表达式了, 在编程语言中逻辑运算过程是这样的,先计算被括号括起来的(1+1)部份, 返回结果2, 然后再与后面的3相乘, 得出结果为6, 在这里括号有优先运算并返回结果的功能。把这个规则套用于上面的JavaScript代码
( function( $ ){ $( ‘body‘ ).css( { ‘background-color‘: ‘#ccc‘ } ); } )
这段代码其实也是一个括号运算, 只不过这个括号返回的并不是四则运算中计算的结果, 而是一个函数。 可以把这个括号运算看成是一个函数执行, 返回的结果可以是基本类型、对象、函数等等。这里还有第二个括号, 第二个括号其实是一个函数调用。在大多数编程语言中, 调用函数的方法都是在函数名后面加上一个括号, 如果有参数, 可以把参数写在括号里面,JavaScript也不例外。所以上面示例代码的整个执行过程是第一个括号返回一个函数, 第二个括号调用第一个括号返回的函数, 整个过程其实就是一个函数调用, 只不过穿上一身奇怪的衣服变的不容易认出来而已。示例的代码其实完全可以被下面的代码替代
function exec( $ ) { $( ‘body‘ ).css( { ‘background-color‘: ‘#ccc‘ } ); }; exec( jQuery );
这段代码比之前的代码易理解很多, 但是两者得到的结果一点区别都没有, 只是写法不同而已。不过这段代码多出来一个函数名, 这个函数是一个全局函数,有引起命名冲突的危险, 这可能就是别人更愿意用使用括号的写法而不愿意用这种写法的原因吧。不过还有其它的方法可以替代使用括号的写法, 而且易理解性也更强一些, 并且也没有全局命名冲突的问题。下面是两种替代的写法
void function( $ ){ $( ‘body‘ ).css( { ‘background-color‘: ‘#ccc‘ } ); }( jQuery ); !function( $ ){ $( ‘body‘ ).css( { ‘background-color‘: ‘#ccc‘ } ); }( jQuery );
这四段示例代码中, 有三个使用的是匿名函数, 一个使用具名函数, 它们之间完全可以互相替代, 并且效果一样, 只是使用具名函数的代码容易引起命名冲突。
-------------分割线-----------------------------------------------------------------------------------------------
上面讲的是被括号括起来的函数的基本运行原理, 但为什么要选择这么做呢? 这么做有什么好处? 这之中涉及到软件工程的信息隐藏机制。在现代流行的面向对象编程语言中, 有类的概念, 类的成员有各种不同的访问修饰public、protected、private, 而在JavaScript中却没有这些, 但是这些特性却可以通过function模拟出来, 以达到类似的功效。在JavaScript中function有其它语言中class的功效。以下面这段代码为例
( function() { var person = []; function setName() { person.push( "name: Sola Aoi" ); } function setAge() { person.push( "age:30" ); } function setGender() { person.push( "gender:female" ); } window[ ‘printPersonInfo‘ ] = function() { setName(); setGender(); setAge(); document.write( person.join( "<br/>" ) ); } })( ); printPersonInfo();
这段代码就起到了很好的信息隐藏作用, 在代码中有一个变量和四个函数, 其中对外公开的就是一个printPersonInfo函数, 其它的几个都被隐藏在括号之中的函数里面。 所以在外面写代码只需要关注命名会不会和printPersonInfo函数冲突, 而不必去管其它三个, 这就相当于代码之中的person、setName、setAge、setGender都是private的, 而只有printPersonInfo是public的。还有一个好处, 你在改动代码之时, 可以任意修改 person、setName、setAge、setGender, 不用担心改动它们会影响到其它地方, 因为它们的作用都被限制在固定的作用域里面了, 只在那一块代码的作用域里被调用, 而不涉及到其它地方。 当然printPersonInfo不可以随意改动, 因为它被设置为对外公开, 在其它任意未知的地方都有可能被调用, 所以不能随意改动。 这种写法在这里效果已经很明显了, 把改动所受的影响从五个减少到了一个, 代码的易维护性大大的提高了。下面是一个Visual Basic版本实现, 实现的效果相同。
Module Module1 Class Person Private Shared person As List(Of String) = New List(Of String) Private Shared Sub SetName() person.Add("name: Sola Aoi") End Sub Private Shared Sub SetGender() person.Add("age:30") End Sub Private Shared Sub SetAge() person.Add("gender:female") End Sub Public Shared Sub PrintPersonInfo() SetName() SetGender() SetAge() Console.Write(String.Join(vbCrLf, person.ToArray())) End Sub End Class Sub Main() Person.PrintPersonInfo() End Sub End Module
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。