函數(shù)表達(dá)式
定義函數(shù)的方法
-
函數(shù)聲明
重要特征:函數(shù)聲明提升 在執(zhí)行函數(shù)之前會(huì)先讀取聲明。也就說(shuō)可以把函數(shù)聲明放在調(diào)用函數(shù)之后
AAAA(1) function AAAA(agr0){ // 函數(shù)體 } -
函數(shù)表達(dá)式(匿名函數(shù))重點(diǎn)
不存在函數(shù)聲明提升,如果在函數(shù)表達(dá)式之前調(diào)用函數(shù),會(huì)報(bào)錯(cuò)
// AAAA(1) var AAAA = function(agr0){ // 函數(shù)體 }
遞歸
經(jīng)典的階乘遞歸
function factorial(num){
if(num<=1){
return 1
}else {
return num * factorial(num - 1)
}
}
var antherFactorial = factorial;
factorial = null;
antherFactorial(4) // 直接報(bào)錯(cuò)
調(diào)用
antherFactorial時(shí),內(nèi)部必須調(diào)用factorial函數(shù),但此時(shí)的factorial函數(shù)已經(jīng)是null,所以會(huì)報(bào)錯(cuò)
非嚴(yán)格模式下解決上述錯(cuò)誤
function factorial(num){
if(num<=1){
return 1
}else {
return num * arguments.callee(num - 1)
}
}
var antherFactorial = factorial;
factorial = null;
antherFactorial(4) // 24
嚴(yán)格模式下并且兼容非嚴(yán)格模式
使用匿名函數(shù)表達(dá)式
var factorial = function f(num){
if(num<=1){
return 1
}else {
return num * f(num - 1)
}
}
var antherFactorial = factorial;
factorial = null;
antherFactorial(4) // 24
閉包
指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)
常見(jiàn)方式:一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。
function createCompare(prop){
return function create(obj1,obj2){ // 匿名函數(shù)
console.log(prop)
var val1 = obj1[prop]; // 訪問(wèn)外部函數(shù)中的變量
var val2 = obj2[prop]; // 訪問(wèn)外部函數(shù)中的變量
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})
閉包與變量
副作用:閉包只能取得包含函數(shù)中任意變量的最后一個(gè)值,閉包保存的是整個(gè)變量對(duì)象,不是某個(gè)特殊的變量
function create(){
var result = [];
for(var i = 0; i<10 ;i++){
result[i] = function(){
return i;
}
}
return result
}
console.log(create()[0]()) // 10
每個(gè)作用域鏈中都保存著
create()的函數(shù)的活動(dòng)對(duì)象,所以實(shí)際上都是引用的同一個(gè)變量i當(dāng)create()函數(shù)返回后,i的值為10,而result每個(gè)函數(shù)都引用著保存變量i的同一個(gè)變量對(duì)象,所以每個(gè)函數(shù)內(nè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
創(chuàng)建一個(gè)匿名函數(shù),且有一個(gè)參數(shù)
num,每次循環(huán)時(shí),會(huì)將i的值賦值給num,num作為最終函數(shù)的返回值。
其實(shí)主要原因還是在于
var,可以定義重復(fù)的變量,可以使用let。
關(guān)于this對(duì)象
var name = 'Global';
var obj = {
name:'Obj',
getName:function(){
return function(){
return this.name
}
}
}
console.log(obj.getName()()) // 'Global'
一般情況下,
this對(duì)象是運(yùn)行時(shí)基于調(diào)用對(duì)象的。匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此this通常指向window
var name = 'Global';
var obj = {
name:'Obj',
getName:function(){
var that = this;
return function(){
return that.name
}
}
}
console.log(obj.getName()()) // 'Obj'
定義匿名函數(shù)之前把
this對(duì)象賦值給了that,that指向的是obj,所以返回的就是obj內(nèi)的name
模仿塊級(jí)作用域
也就是我們常說(shuō)的防止變量污染,匿名函數(shù)中定義的任何變量,執(zhí)行結(jié)束后都會(huì)被銷毀。
var i = 1;
(function(){
var i = 10;
})()
console.log(i) // 1
// function(){
// }()
// 這種寫(xiě)法會(huì)報(bào)錯(cuò)
// var AA= function(){
// }()
// (function(){
// var i = 10;
// })()
// 正確寫(xiě)法
// 匿名函數(shù)執(zhí)行之后銷毀了變量------------>>>>節(jié)省內(nèi)存
var aa = function(){
var b = 1;
}
aa();
console.log(b) // b is not defined