函数
函数提升
- 函数声明提升
执行代码之前会先读取函数声明。意思是可以把函数声明放到调用它的语句后面
sayHi()
function sayHi(){
*****
}
- 函数表达式
var functionName = function(arg0, arg1, arg2){
*****
}
这个就不能把函数放到调用它的语句后面了,会报错
- 理解函数提升的关键,就是理解函数声明和函数表达式之间的区别。
//不要这么写
if (condition) {
function sayHi(){
console.log('Hi')
}
}else {
function sayHi(){
console.log('Hello')
}
}
这在ECMAScript上属于无效语法,JavaScript引擎会尝试修正错误,将其转换为合理的状态。大多数浏览器会返回第二个声明,忽略condition。Firefox会在condition为true时返回第一个声明。
可以这样做,用函数表达式:
let sayHi
if(condition){
sayHi = function(){
console.log('Hi')
}
}else {
sayHi = function(){
console.log('Hello')
}
递归
js在递归里面可以使用arguments,callee来防止函数名被置空的情况,例如:
function factorial(num) {
if(num <= 1){
return 1
} else {
return num * factorial(num - 1)
}
}
var anotherFactorial = factorial
factorial = null
console.log(anotherFactorial(4))
上面factorial函数被置空之后,程序就会报错:
我们可以这样解决
function factorial(num) {
if (num <= 1){
return 1
} else {
return num * arguments.callee(num - 1)
}
}
又或者是这样
创建一个名为f()的命名函数表达式
var factorial = function f(num) {
if(num <= 1){
return 1
}else {
return num * f(num-1)
}
}
闭包
闭包是指有权访问另一个函数作用域中的变量的函数。
如何创建作用域链以及作用域链有什么作用的细节,对彻底理解闭包至关重要。
- 函数的调用过程:
1、创建一个执行环境execution context
及相应的作用域链
2、把作用域链赋值给一个特殊的内部属性[Scope]
3、用this、arguments和其他命名参数的值来初始化函数的活动对象(activation object
)
例如
function compare(value1,value2){
if(value1 < value2){
return -1
}else if(value1 > value2){
return 1
}else{
return 0
}
}
书上的图
一般作用域链包含两个变量对象:本地活动对象以及全局变量对象
闭包不同
未完待续
网友评论