一小段js代码的思考(1)
今天随手写了一段代码,被@流浪大法师吐槽了,于是整理出了关于一个比较友善的写法以及在这段代码中的思考。
本篇有一点js trick在里面,也有模块化、函数科里化的一些写法。
先看下面的糟糕的第一段代码
:
1 | var test = (function(arg0){ |
这里我犯了一个错误,我习惯性地将函数最外层用括号包起来使其立即执行,这是声明式的用法,在这里运用错误。函数有两种形式,表达式和声明式,函数表达式本身可以立即执行。
第二段代码
修改了一下
1 | var test2 = function(arg0){ |
去掉最外层括号之后本段代码也立即执行了。
若要让声明式立即执行,需要加一些小技巧。
最常见的写法
:
1 | (function(){//这里的代码立即执行 |
奇特的写法
:
赋值,逻辑,甚至是逗号,各种操作符都可以告诉解析器,这个不是函数声明,它是个函数表达式。
1 | !function(){alert("aaa")}//可以使用+-~void new delete |
在chrome中的执行结果如下:
截图中可以看出,inner部分直接执行了,调用test()的时候return的匿名函数执行了。
因为之前写别的语言的缘故,习惯在函数的起始位置就传参,由于本段代码是立即执行的,所以第一次传参并没有起作用,后续的函数调用根本就没有调用到,这种写法真是太糟糕了。
以下是第三段代码
1 | var test3 = function(arg0){ |
在chrome中的执行结果如下:
这里放弃了立即执行,采用需要时调用的方式。
第一次调用函数表达式,第二次调用返回的匿名函数,根据调用次序的不同,可以满足不同的业务需求。
第一次调用时,传参进行初始化,参数在函数作用域中声明,当函数执行完毕之后,被gc掉(属于标记清除)。
第二次调用使用的是返回的函数,这里是一个闭包,注意执行的时候要谨慎,不要轻易赋值给全局变量,内存泄漏你们都懂。
第四段代码
是高阶函数的写法
1 | //code4-1 |
code4-1是标准的高阶函数调用,在需要的时候将函数作为参数传入,code4-2通过返回匿名函数的方式传参。在这里优势不明显,研究完继续填坑。
接下来看第五段代码
1 | //moduleC |
这是commonjs的写法,这样写也为了函数解耦,个人觉得将函数绑定到对象的属性属于面向对象编程,和前面的说明式编程思想是不一样的。
1 | > 批注:[2016-4-17修正] |
还有第六段代码
1 | //moduleA.js |
pay attention
这种写法在nodejs中非常常见,这样写更符合事件触发机制,适用于将函数的执行作为参数传入,表示事件的传入,而事件发生时传参执行。
moduleA返回了函数对象,函数对象的属性的值是匿名函数,在moduleB中require了moduleA的返回函数,当需要使用moduleA的方法时,可以通过对象的键值调用。
思考
:
本文通过执行调用的顺序,结合以前写代码的习惯,讨论了javascript书写方式,若实践中得到更好的方式本文将持续修改。