拖延症晚期癌,每次都是周日最后一个小时才开始动笔,先鄙视下自己
今天要“弹”的是一个有点被说“烂”了的话题,在JavaScript里,函数是一等公民(哇,听起来很高大上吧),而同时在这个函数式编程异常火爆的年代,你到底该怎么理解“函数是一等公民”这句话呢?
其实,我们也可以换个角度来看,在JavaScript里,任何东西都是对象(嗯,还是要刨掉原始类型),作为一个后端狗,在读《Java编程思想》这部“巨著”的时候,记得有那么一句“万事万物皆是对象”,那么在JavaScript里离这句话就更近了一些,下面就先看一个例子吧
var log = function(a){
console.log("invoke:"+a);
}
log.name = "日志";
console.log(log.name);
这里,我们不仅可以将一个函数赋值给一个变量,甚至还可以给这个变量再增加一个属性。那么上面这个log
这个到底是个函数呢还是个对象呢?
其实,在JavaScript里,函数只是一个更特殊的对象,他首先拥有对象的一切能力,接着,他还有额外的一个特殊的部分,可以成为执行部分,或是代码部分,那么接着一个更酷的事情就是,我们可以这样使用log
这个变量。
var log = function(a){
console.log("invoke:"+a);
}
log.name = "日志";
log("Just A Test");
这段代码,将会输出
invoke:Just A Test
嗯,如果将一个函数赋值给一个变量之后,我们只需要在这个变量后面增加()即,代表这是一个函数式的对象,可以执行,这里()更适合一种“运算符”,嗯,就叫执行运算符。
而如果一个变量本身不是指向的了一个函数的话,强行调用()会报错,我们可以试试这样一段代码
var a = {
"name" : "value"
}
a();
这里,我们定义了一个变量a,而变量a实际“指向”的是一个对象,并不是函数,这时我们强行调用()的话,会报这样的错误:
Uncaught TypeError: a is not a function
报错信息很明确,a并不是一个函数。
另外,有关前面曾经聊过的“变量提升”的问题,这里也是需要再说一说的。
我们之前明确过,一个函数定义是会在运行时环境构建的适合就处理完成,因此一个函数的定义和调用的顺序是无关的。
比如这段代码
log("just a test");
function log(a){
console.log(a);
}
这里我们已经很清楚,是可以正确执行的,那么如果我们换一种方法呢:
log();
var log = function(a){
console.log(a);
}
这时是会报错的:
Uncaught TypeError: log is not a function
因为这里,log只是一个普通的变量,JavaScript的运行时环境并不会把他作为一个函数,对他提前的初始化,这样的报错就更好理解了。
那么对于函数式编程在JavaScript里的运用,那就更是一个有意思的话题了,今天我们只是框清了一个概念“在JavaScript里,函数只是一个特殊的对象而已”