有时候看一些jQuery插件的代码前面总是会有一些特殊的字符放在最前面,比如!、~、+、搞不懂到底有什么用?不知各位有没有产生过这种疑惑。
那么现在我就用一句话概括一下这些看似无用的符号所起到的作用。
像!、+、-、||、&&等这些东西的存在是为了告诉解析器,要把下面的代码当作表达式执行,而不是函数!更直白的说就是告诉浏览器,下面这个没名字(匿名)的函数要当作匿名函数(或者说是立即执行函数)来解析。
一句话说完了,没看明白?那我就来按照这句话中的关键字简要的解释一下这句话的意思吧。
一、这句话的上下文
!、+、-、||、&&等符号的后面都是跟着一个function关键字的,他的结构就如下面的代码定义方式:
+function ($) {
//code
}();
二、解析器‘优待’函数申明
浏览器在解析js代码的过程中涉及到一个扫描‘预编译’的过程(PS:不知道这么说合理否,毕竟js是解释型语言,和java这种编译语言处理过程是有差异的),这个过程中会有以下两个操作:①用var声明的变量设置为活动对象的属性,默认值为“undefined”,②以function定义的函数也添加为活动对象的属性,而且他们的值正是函数的定义;
与本文密切相关的第二步,function申明的函数将‘优先’处理。而用var 定义的函数表达式则被浏览器视为普通表达式,在解析器顺序执行js代码的时候才给这个定义的函数名设值。
这段话的代码解释:
函数申明方式:
var a = beloved();
console.log(a);
function beloved() {
return 'ok';
};
函数表达式方式:
var b = notgood();
console.log(b);
var notgood = function () {
return 'bad';
}
执行结果:‘
三、浏览器不喜欢没名字的‘孩子’
第二部分我们已经说明了js代码的执行顺序,但是我们发现,不管是在“预编译”的时候执行,还是在正式解析的时候执行,只要按照正常的函数结构来定义函数,都能被浏览器识别,但是可能是“计划生育”的原因,有些是js代码“超育超生”,没法给函数这个“函数小朋友”上户口(匿名函数),就像这样:
function () {
alert('i have noting,even a name.')
}
执行结果:
但是又想让他在这个特殊的空间里“施展拳脚”,怎么办?“人怕出名猪怕壮”,我们偷偷的把他打扮一下,搞成个普通的不能在普通的“小朋友”,而不要像function那样被“优待”不就行了?!
(function () {
console.log('i have noting,but i can run now.')
}());
执行结果:
就是这样的包装,这个没有名字的“小朋友”,在今后的岁月中在闭包、模块编程方面做出了“杰出贡献”。
四、喜欢怎么写就怎么写
前三部分用了一些 不太恰当的例子讲了两个基础的知识,下面就切入正题,先看代码:
function () {
console.log('are you ok!!!')
}();
执行结果:
(function () {
console.log('i am very ok!!!')
}())
!function () {
console.log('i am very ok!!!')
}();
~function () {
console.log('i am very ok!!!')
}();
+function () {
console.log('i am very ok!!!')
}();
true&&function () {
console.log('i am very ok!!!')
}();
执行结果:看了代码,估计大家都已经最开始那句话解释的意思了把,不明白那就在罗嗦一遍,这些符号的存在,就是告诉浏览器,“我是一个普通通的表达式,请你在正式执行的时候再解析我,而不是在预编的时候!”,符号就是在帮助匿名函数做“伪装”!好啦,要说的东西解释完毕!
其实匿名函数(立即执行函数)的写法是很随意的,你可以用任何自己习惯的写法来书写代码,也可以使用new关键字,像这样:
0, function () { /* code */ }();
new function() { /* code */ }()
五、这个东西不一样
都介绍完了还有什么?这个不可缺少的东西就是分号(;)!!!
这个东西为啥不一样?先看代码:
情况一:
情况二:
// a.js
function purpose() {
console.log('i come from a.js')
};
purpose()
// 忘记加分号了
//b.js
(function sayok() {
console.log('b.js')
}());
执行结果:
// a.js
function purpose() {
console.log('i come from a.js')
};
purpose()
// 忘记加分号了
//b.js
;(function sayok() {
console.log('b.js')
}());
执行结果:
首先:我们可以发现,分号(;)是不可以放在立即执行函数前面的,它不具有转换function函数为表达式的功能,反而会告诉浏览器,“你看,就是家伙没户口”。再次:当我们在压缩合并同事间合作完成的代码时,就会出现第一种错误,由于别人漏泄了分号,自己的代码跑不转了,说不定你还要找好久出现的问题到底在哪。其实就是这个看着不起眼的分号。希望这个小tips能够帮助大家,在书写规范代码的问题上与君共勉。
因个人水品有限,总结的知识如果存在错误或者漏洞,请指出,感谢!