函数表达式的两种:
1.函数声明:首先是function关键字,然后是函数的名字特征是函数声明提升,就是在执行代码之前会把函数名提到最上面。 1-1
2.函数表达式:创建一个函数并将它赋值给变量也叫做匿名函数,因为function关键字后面没有标识符(匿名函数 有时候也叫做拉姆达函数),匿名函数的name是空字符串。 1-2
//1-1 函数声明
funtion fn(){
console.log(函数声明)
}
//1-2 函数表达式
var myFunction = function(){
console.log(函数表达式)
}
递归
递归:递归函数是在一个函数通过名字调用自身的情况下构成。
//这是一个经典的递归阶乘函数
function fn(num){
if(num<=1){
return 1
}else{
return num * fn(num-1)
}
}
这是一个经典的递归结成函数。虽然这个函数表面看来什么问题,但下面的代码却可能导致他出错
var another = fn
var fn = null
alert(anoter(4))
这段代码我们把fn存在了anoher变量中然后将fn变量设置为null但在接下来调用another,由于必须执行fn,而fn已不再是函数,所以就会导致错误,在这种情况下agrumebts.callee可以解决这个问题,当然是在非严格模式下
function fn(num){
if(num<=1){
return 1
}else{
return arguments.callee(num-1)
}
}
//arguments.callee表示正在执行的函数
那么我们在严格模式下怎么处理上面这种情况呢?
var fn = (function f(num){
if(num<=1){
return 1
}else{
return num * f(num-1)
}
})
闭包
闭包的概念:函数可以通过作用域链相互关联起来,函数体内部的变量可以保存在函数作用域内,子函数通过作用域链获取父集函数的变量。
为什么要使用B包?
1.因为B包可以访问到函数内部的变量并且会将这些变量的值一直保存在内存中。
2.因为B包引用函数不会被清除,可能会造成内存泄漏的问题,特别是IE
B包的特性?
1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾机制回收
块级作用域
我们为什么要使用块级作用域,下面来看下下面的代码。
var num = 1
function fn(){
console.log(num) //undefined
if(false){
var num =2
}
}
可以看到我们console.log的结果为undefined为什不是读取全局的num呢因为在函数体内部,函数会把所有的变量名提到做上面并赋值undefined所以num到fn函数里面又给赋值了所以undefined。那么我们用块级作用域解决这个问题。
var num = 1
function fn(){
console.log(num) //1
(function (){
if(false){
var num =2
}
}())
}
fn()