函數(shù)的本質(zhì)
什么是函數(shù)夯尽?
阮一峰給了我們很好地解釋?zhuān)汉瘮?shù)就是一段可以反復(fù)調(diào)用的代碼塊谊娇。函數(shù)還能接受輸入的參數(shù)赠堵,不同的參數(shù)返回不同的值半等。
聽(tīng)不懂莽囤?那我下面的求三角形面積的例子演示一遍谜悟。
那問(wèn)題在于掠归,我們?nèi)绾沃肋@段函數(shù)在內(nèi)存里面是怎么存的?作為一個(gè)程序員悄泥,我們必須知道虏冻,當(dāng)一個(gè)東西被聲明出來(lái)之后,它在內(nèi)存里面是怎么存的弹囚。
那么函數(shù)要怎么存厨相?難道就當(dāng)成字符串來(lái)存在內(nèi)存里嗎?對(duì)的鸥鹉,沒(méi)錯(cuò)蛮穿,函數(shù)就是被當(dāng)做字符串存起來(lái)的:
函數(shù)的整體體系:
函數(shù)的 5 種聲明
- 變量可以是7種數(shù)據(jù)類(lèi)型:
number
String
Boolean
symbol
undefined
null
Object
- 但是,如果是function聲明一個(gè)函數(shù)x毁渗,那么這個(gè)x只能是對(duì)象里的函數(shù)践磅。這是變量的特例。
- 控制臺(tái)運(yùn)行一段代碼時(shí)灸异,打印出的內(nèi)容和返回的內(nèi)容一點(diǎn)關(guān)系都沒(méi)有
- 第一種方法:具名函數(shù)
function f(x,y){
return x+y
}
f.name // 'f'
- 第二種方法:匿名函數(shù)
var f
f = function(x,y){
return x+y
}
f.name // 'f'
如果要聲明一個(gè)匿名函數(shù)必須賦值給另外一個(gè)變量
- 第三種 具名函數(shù)賦值 面試常用到
var f
f = function f2(x,y){ return x+y }
f.name // 'f2'
console.log(f2) // undefined
如圖府适,黑色的代碼的Y的作用域就在綠色圈圈內(nèi),即使在外面也能訪問(wèn)Y肺樟,下面藍(lán)色的代碼的Y的作用范圍就只能函數(shù)的里面檐春,也就是只能在綠圈圈里面訪問(wèn)Y。這叫做作用的區(qū)域么伯。這兩種語(yǔ)法并沒(méi)有區(qū)別疟暖,所以這就是不一致性,所有的不一致性都是垃圾
- 第四種 window.Function(不常用)
聲明方式:所有部分都是用字符串表示田柔,字符串可以拼接起來(lái)俐巴,拼接期間可以添加變量
var f = new Function('x','y','return x+y')
f.name // "anonymous"
- 第五種 箭頭函數(shù)
var f = (x,y) => {
return x+y
}
var sum = (x,y) => x+y
var n2 = n => n*n
- 五種函數(shù)聲明方式總結(jié)
函數(shù)的name屬性
函數(shù)的name:面試常踩坑
eval命令
eval的作用是,把字符串當(dāng)作代碼執(zhí)行.(少點(diǎn)用)
如何調(diào)用函數(shù) f.call() 執(zhí)行對(duì)象的函數(shù)體
- f和f.call()
- f()和f.call()
大部分人都會(huì)用f()
調(diào)用函數(shù)硬爆,但是f.call()
才是真正的調(diào)用欣舵。f()
是一個(gè)語(yǔ)法糖,f.call
為硬核玩家摆屯。如果想學(xué)好this,那就必須用f.call().
- f.call()用法
this 和 arguments
- f.call(asThis, input1,input2)
其中 asThis 會(huì)被當(dāng)做 this邻遏,[input1,input2] 會(huì)被當(dāng)做 arguments
function f(){
'use strict'
console.log(this)
console.log(arguments)
return undefined
}
f.call(1,2,3) // this 為 1,arguments 為 [1,2,3]
禁止使用 f(input1, input2)
- undefined就是this虐骑,this也就是call()的第一個(gè)參數(shù)
- this后面的參數(shù)都是arguments
- JS第一個(gè)參數(shù)為什么是this?
歷史原因:JS之父設(shè)計(jì)JS的時(shí)候?yàn)榱藵M(mǎn)足上司說(shuō)JS語(yǔ)言必須與JAVA語(yǔ)言類(lèi)似的需求准验,而臨時(shí)加了this,來(lái)表示第一個(gè)參數(shù)廷没。
- 普通模式
- 嚴(yán)格模式
call stack 調(diào)用棧
每進(jìn)入一次函數(shù)糊饱,就要壓一次stack
什么是Stack Overflow?
比如上面我們求5次颠黎,就要壓5次棧另锋,若是求100次呢滞项?1000次,10000次甚至更多呢夭坪?我們來(lái)試試把棧爆掉:
作用域樹(shù)形圖
- 當(dāng)我們?cè)谝粋€(gè)函數(shù)里面聲明變量文判,如果找不到這個(gè)變量,就往父級(jí)找室梅。按照語(yǔ)法樹(shù)戏仓,就近原則
- 我們只能確定變量是哪個(gè)變量,但是不能確定變量的值
- 只要有一個(gè)函數(shù)亡鼠,就有一個(gè)作用域
- 作用域面試題:拿到題目先使用變量提升赏殃,把所有的聲明都提升到上面,把所有的執(zhí)行都放到下面