函数表达式
定义函数的方式有两种,一是函数声明,一是函数表达式。使用函数声明会有函数声明提升(在执行代码之前会先读取函数声明,即在函数调用后声明函数语句不会报错),函数表达式没有函数声明提升。
var functionName=function(arg0,arg1,arg2){
//函数体
}
递归
递归是函数调用自身的过程。
function factorial(num){
if(num<=1){
return 1
}else{
return num*factorial(num-1)
}
}
var anotherFactorial=factorial
anotherFactorial(10) //3628800
factorial=null
anotherFactorial(10) //报错,factorial不是一个函数
在递归过程中,若递归的函数引用被切断,递归就会出错。
解决上述问题的方法有以下几种:
- argument.callee(非严格模式下)
function fact(num){
if(num<=1){
return 1
}else{
return num*arguments.callee(num-1)
}
}
var anotherFact=fact
anotherFact(10) //3628800
factorial=null
anotherFact(10) //3628800
- 命名函数
var factorical=(function fact(num){
if(num<=1){
return 1
}else{
return num*fact(num-1)
}
})
var anotherFact=factorical
anotherFact(10) //3628800
factorial=null
anotherFact(10) //3628800
闭包
- 理解闭包
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的方式为在一个函数内部创建另一个函数。
function createCompareFunction(propertyName){
return function(object1,object2){
var value1=object1[propertyName]
var value2=object2[propertyName]
if(value1>value2){
return 1
}else if(value1<value2){
return -1
}else{
return 0
} }
}
当函数被调用时,会创建一个执行环境及相应的作用域链。然后,使用arguments和其他命名参数的值来初始化函数的活动对象。在作用域链中,当前函数的活动对象位于第一位,外部函数的活动对象位于第二位,外部函数的外部函数的活动对象位于du第三位,直到作用域链终点的全局执行环境。
闭包中函数通过作用域链访问变量,从作用域链的顶点开始搜索,直至作用域链的终点。
作用域链保存在函数的内部[[scope]]属性中。
2.闭包的问题
- 一般情况中,当函数执行完毕后,局部活动对象就会被销毁,只有全局作用域的变量会存在在内存中。但在闭包中,由于外部函数的引用没有被解除,即使函数已经执行完毕,变量也不会被销毁。
- 闭包只能取得包含函数中任何变量的最后一个值。
- 闭包中的this
匿名函数的执行环境具有全局性
var name='window'
var object={
name:'object',
getNameFunc:function(){
return function(){
return this.name
}
}
}
object.getNameFunc()() //window
模仿块级作用域
JavaScript没有块级作用域,在块语句中定义的变量,在外面也可以访问。
for(var i=0;i<10;i++){
console.log(i)
}
console.log(i)//10
通过匿名函数模仿块级作用域。
(function(){
//块级作用域
for(var i=0;i<10;i++){
console.log(i)
}
})()
console.log(i)//报错
私有变量
JavaScript中没有私有变量的概念,但是可以将函数中的变量当作私有变量,函数外部不能访问函数内部的变量。
特权方法指的是有权访问私有变量和私有函数的公有方法。
function Person(){
//私有变量
var name='marry'
//特权方法
this.getName=function(){
return this.name
}
}
静态私有变量
在私有作用域下定义私有变量或函数,创建特权方法。
(function(){
//私有变量
var name=""
//构造函数
Person=function(value){
name=value
}
//特权方法
Person.prototype.getName=function(){
return name
}
Person.prototype.setName=function(value){
name=value
}
}
)()
模块模式
模块模式指的是为单例创建私有变量和特权方法。单例指的是只有一个实例的对象。下面以对象字面量形式创建单例对象。
var singleton={
name:value,
method:function(){
}
}
模块模式的语法形式:
var singleton=function(){
//私有变量和函数
var privateVar=10;
function privateFunction(){
return false
}
//特权方法和公共属性
return {
publicProperty:true,
publicMethod:function(){
privateVar++;
return privateFunction
}
}
}()
增强的模块模式
在返回对象之前添加增强代码。
var singleton=function(){
var privateVar=10
function privateFunction(){
return false
}
var object=new CustomType() //创建特定对象
object.publicMethod=function(){
privateVar++
return privateFunction()
}
return object
}()