一,普通的函数中定义函数
首先要区分:函数中定义的函数,和函数作为对象,并给这个对象定义的方法。这两者是不一样的。
函数中定义的函数:需要从数据类型的角度理解,一旦执行这个函数,就会定义出内部一个函数。因为作用域的存在,无法在外面直接调用访问。但是可以在这个函数内直接使用。
function Foo(){
getName=function(){
//虽然这里没有用var,定义的是全局的,外部直接访问是无法访问的。
alert(1)
} //这里定义一个函数(从数据类型角度理解),因为是定义在函数内部的函数,外部直接访问是无法访问的。
return this
}
函数作为对象,定义的方法:函数在对象中,又被称为方法,这时候,是可以通过点或者【】来访问调用的。
function Foo(){
getName=function(){
//虽然这里没有用var,定义的是全局的,外部直接访问是无法访问的。
alert(1)
} //这里定义一个函数(从数据类型角度理解),因为是定义在函数内部的函数,外部直接访问是无法访问的。
return this
}
//Foo.getName() // Foo.getName is not a function
Foo.getName=function(){
alert(2)} //把Foo作为一个函数对象!给它写方法getName
Foo.getName() //2,这时候是这个函数对象的方法
二,从外部调用函数内部函数的渠道
函数对象的方法已经很熟悉了,无需多说,就讲从函数外部如何调用内部的函数和变量。
第一种,定义在函数内部,但是是全局作用域的函数和变量:
function Foo(){
var b=2 //这个函数作用域内的变量
c =3 //全局作用域的变量
getName=function(){
//全局作用域的函数
console.log('函数被调用成功')
}
return this
}
// console.log(c) 会报错,因为此时全局上还没有这个变量
// getName() 会报错,因为此时全局上还没有这个函数
Foo() //执行Foo函数,然后会在window上生成getName函数和c变量
getName() //此时window上已经有这个函数了
// console.log(b) //b is not defined //因为是函数作用域内的变量,外部无法直接访问
console.log(c) //c是在函数定义的全局变量
从内存角度理解就是下图这样,函数Foo执行完毕后在全局在全局生成了对应的数据。
第二种:定义在函数内部,作用域也在函数内:
function Foo(){
var b=2 //这个函数作用域内的变量
var c =3 //函数作用域内的变量
var getName=function(){
//函数作用域内的函数
console.log('函数被调用成功')
}
return this
}
Foo() //执行Foo函数,先生成函数上下文,然后执行完毕后销毁
getName() //此时window上并没有有这个函数,报错
console.log(c) //此时window上并没有有这个变量,报错
想要执行函数内部的函数,需要在全局定义全局变量,然后再在调用函数时,将函数中的值保存到变量中去:
var fn
var c2
function Foo(){
var b=2 //这个函数作用域内的变量
var c =3 //函数作用域内的变量
var getName=function(){
//函数作用域内的函数
console.log('函数被调用成功')
}
fn=getName
c2=c
return this
}
Foo() //执行Foo函数,先生成函数上下文,然后执行代码,并将对应的数据保存到全局变量上,完毕后销毁上下文
fn() //函数被执行
console.log(c2) //3
从内存角度理解就是下图这样:
变量和函数虽然在函数Foo执行结束后,函数上下文虽然弹出栈并销毁了,但是在函数执行过程中,已经把对应的变量和函数赋值给全局中的变量了。