JavaScript之函数类型

让我们直接进入函数声明和函数表达式,看看如何在JavaScript中使用这两种类型的函数。如果不仔细看,两者可能非常相似:

//函数声明
function isLie( cake){
return cake === true;
}
//函数表达式
var isLie = function(){
return cake === true;
}


二者之间唯一的区别发生在赋值期间。解释器可以在语法解析期间访问到函数声明。而函数表达式是赋值表达式的一部分,在整个程序赋值完成前都不能执行。这点区别看起来很小,但是影响很大。考虑一下这种情况:

declaration(); //我是一个函数声明
function declaration(){
console. log( '我是一个函数声明');
}
expression(); //Uncaught TypeError: undefined is not a function
var expression = function(){
console. log( '我是一个函数表达式');
}


就像前面的例子里所看到的,函数表达式在被调用时抛出了异常,但函数声明执行正常。这个异常揭示了函数声明和函数表达式的关键不同。JavaScript可以理解声明的函数,并能在程序执行前将函数解析。因此,函数的调用在声明前后都没关系,因为JavaScript在幕后已经将函数提升到当前作用域的顶端。而函数表达式直到变量被赋值时才进行计算,因此当它被调用时仍是undefined。所以优秀的代码风格应该在当前作用域的顶端定义所有变量。这样做的话,脚本的顺序就跟JavaScript语法解析时的顺序就一样了。

前面省略了一个概念,当语法解析时,JavaScript会把所有函数声明移到当前作用域的顶端。所以声明式函数可以放在脚本的任意位置。为了更进一步探索声明和表达式之间的区别,看看这个例子:

function sayHi(){
console. log( 'hi');
}
var hi = function sayHi(){
console. log( 'hello');
}
hi(); //hello
sayHi(); //hi


你在看这段代码的时候可能会以为函数声明会崩溃,因为它跟函数表达式重名了。然而因为第二个函数是赋值变量的一部分,拥有自己的作用域,所以JavaScript把它们当成不同的实体。

下面的例子可能更让人困惑:

var sayHo;
console. log( typeof( sayHey)); //function
console. log( typeof( sayHo)); //undefined
if( true){
function sayHey(){
console. log( 'hey');
}
sayHo = function sayHo(){
console. log( 'ho');
}
} else{
function sayHey(){
console. log( 'no');
}
sayHo = function sayHo(){
console. log( 'ho');
}
}
sayHey(); //no
sayHo(); //no


在前面的例子中,你已经看到了拥有相同名字的函数声明和函数表达式会被区别对待。在这个例子中,我会尝试基于程序运行的方式来按条件定义函数。看到这段脚本的控制流时,你可能会期待sayHey返回‘hey’,因为条件声明的执行结果为真。试试恰恰相反,返回的结果是‘no’,也就是说第二个版本的sayHey函数取代了第一个。更让人困惑的是sayHo函数的行为完全相反,这可以再次归结为编译时和运行时之间的差异。

你已经知道JavaScript会在解析脚本时把所有的函数声明放到当前作用域的顶端。在这个过程中,处在同一个作用域的第二个函数取代了第一个函数。这就是为什么会返回‘no’。你也知道函数表达式在赋值过程完成前都会被解析器忽略。赋值跟条件声明的计算一样在运行时发生。这就是为什么sayHo函数可以按条件定义。这里的关键是函数声明不能被条件式的定义。如果你需要条件定义,那就应该用函数表达式。此外,函数声明永远不应该放到控制流语句里,因为不同解释器的处理方式会不一样。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值