函数表达式
定义函数的方法
-
函数声明
重要特征:函数声明提升 在执行函数之前会先读取声明。也就说可以把函数声明放在调用函数之后
AAAA(1) function AAAA(agr0){ // 函数体 }
-
函数表达式(匿名函数)重点
不存在函数声明提升,如果在函数表达式之前调用函数,会报错
// AAAA(1) var AAAA = function(agr0){ // 函数体 }
递归
经典的阶乘递归
function factorial(num){
if(num<=1){
return 1
}else {
return num * factorial(num - 1)
}
}
var antherFactorial = factorial;
factorial = null;
antherFactorial(4) // 直接报错
调用
antherFactorial
时,内部必须调用factorial
函数,但此时的factorial
函数已经是null,所以会报错
非严格模式下解决上述错误
function factorial(num){
if(num<=1){
return 1
}else {
return num * arguments.callee(num - 1)
}
}
var antherFactorial = factorial;
factorial = null;
antherFactorial(4) // 24
严格模式下并且兼容非严格模式
使用匿名函数表达式
var factorial = function f(num){
if(num<=1){
return 1
}else {
return num * f(num - 1)
}
}
var antherFactorial = factorial;
factorial = null;
antherFactorial(4) // 24
闭包
指有权访问另一个函数作用域中的变量的函数
常见方式:一个函数内部创建另一个函数。
function createCompare(prop){
return function create(obj1,obj2){ // 匿名函数
console.log(prop)
var val1 = obj1[prop]; // 访问外部函数中的变量
var val2 = obj2[prop]; // 访问外部函数中的变量
if(val1 < val2){
return -1
}else if(val1 > val2){
return 1
}else{
return 0
}
}
}
var compare = createCompare('name');
var result = compare({'name':1},{'name':2})
闭包与变量
副作用:闭包只能取得包含函数中任意变量的最后一个值,闭包保存的是整个变量对象,不是某个特殊的变量
function create(){
var result = [];
for(var i = 0; i<10 ;i++){
result[i] = function(){
return i;
}
}
return result
}
console.log(create()[0]()) // 10
每个作用域链中都保存着
create()
的函数的活动对象,所以实际上都是引用的同一个变量i
当create()
函数返回后,i
的值为10
,而result
每个函数都引用着保存变量i
的同一个变量对象,所以每个函数内部的值都为10
function create(){
var result = [];
for(var i = 0; i<10 ;i++){
result[i] = function(num){
return function(){
return num
};
}(i)
}
return result
}
console.log(create()[0]()) // 0
创建一个匿名函数,且有一个参数
num
,每次循环时,会将i
的值赋值给num
,num
作为最终函数的返回值。
其实主要原因还是在于
var
,可以定义重复的变量,可以使用let
。
关于this
对象
var name = 'Global';
var obj = {
name:'Obj',
getName:function(){
return function(){
return this.name
}
}
}
console.log(obj.getName()()) // 'Global'
一般情况下,
this
对象是运行时基于调用对象的。匿名函数的执行环境具有全局性,因此this
通常指向window
var name = 'Global';
var obj = {
name:'Obj',
getName:function(){
var that = this;
return function(){
return that.name
}
}
}
console.log(obj.getName()()) // 'Obj'
定义匿名函数之前把
this
对象赋值给了that
,that
指向的是obj
,所以返回的就是obj
内的name
模仿块级作用域
也就是我们常说的防止变量污染,匿名函数中定义的任何变量,执行结束后都会被销毁。
var i = 1;
(function(){
var i = 10;
})()
console.log(i) // 1
// function(){
// }()
// 这种写法会报错
// var AA= function(){
// }()
// (function(){
// var i = 10;
// })()
// 正确写法
// 匿名函数执行之后销毁了变量------------>>>>节省内存
var aa = function(){
var b = 1;
}
aa();
console.log(b) // b is not defined