函數(shù)
函數(shù)概述
函數(shù) 實(shí)際就是多行代碼的抽日浞弧(多行代碼會(huì)構(gòu)成特定的功能)(方法)
函數(shù)的優(yōu)點(diǎn)
減少冗余代碼(重復(fù)的代碼放在函數(shù)里面 在需要的時(shí)候調(diào)用)函數(shù)封裝(特定的一些代碼使用函數(shù)來包起來),
提高了代碼的可維護(hù)性及可閱讀性
函數(shù)的分類
系統(tǒng)函數(shù) window里面的所有函數(shù)都屬于系統(tǒng)函數(shù) (console.log() alert() prompt()...)
內(nèi)置函數(shù) 所有的內(nèi)置對象里面的函數(shù) 都叫內(nèi)置函數(shù) (Math.pow())
自定義函數(shù)( 自己定義的函數(shù))
內(nèi)置函數(shù)和系統(tǒng)函數(shù)我們更關(guān)注于他的使用 自定義函數(shù)(定義以及使用)
自定義函數(shù)的定義以及調(diào)用
1.使用function關(guān)鍵詞 定義匿名函數(shù)(沒有名字的函數(shù))
function(形參(可以省略的 可以有多個(gè))){
函數(shù)體(代碼)
}
//直接調(diào)用 讓別人(事件)去調(diào)用(自動(dòng)調(diào)用)
(function(){
console.log('匿名函數(shù)')
})()
//直接調(diào)用 讓別人(事件)去調(diào)用(自動(dòng)調(diào)用)
(function(){
console.log('匿名函數(shù)')
})()</pre>
匿名函數(shù) (聲明比較少 他沒有復(fù)用價(jià)值)
2.使用function關(guān)鍵詞 定義具名函數(shù) (有名字的函數(shù))
function 函數(shù)名(形參,形參...){
函數(shù)體(代碼)
}
function 函數(shù)名(形參,形參...){
函數(shù)體(代碼)
}
//聲明 具名函數(shù)(第一種)
function sayHello(){
console.log('hello')
}
sayHello()
3.使用new Function方式
var 函數(shù)名 = new Function('形參,形參1','函數(shù)體')
//定義
var sayBye = new Function('console.log("bye bye!!")')
//調(diào)用
sayBye()
//傳參
var sayBye = new Function('username','console.log("bye bye!!"+username)')
//調(diào)用
sayBye('李四')
在程序執(zhí)行之前有個(gè)預(yù)編譯過程
預(yù)編譯會(huì)做的事情
1.他會(huì)聲明對應(yīng)的function和var關(guān)鍵詞修飾的變量(開辟內(nèi)存的操作)
2.對應(yīng)的function的內(nèi)存空間開辟以后他會(huì)將對應(yīng)的代碼塊放到其中 等待調(diào)用
3.var 修飾的關(guān)鍵詞 只會(huì)開辟一個(gè)空間 并不會(huì)進(jìn)行賦值(默認(rèn)給他的一個(gè)undefined的值)
return關(guān)鍵詞
- return 返回對應(yīng)的數(shù)據(jù)的 他是在函數(shù)內(nèi)容進(jìn)行數(shù)據(jù)返回的(當(dāng)你調(diào)用了
return操作后 后面的內(nèi)容將不再執(zhí)行)
2)如果沒有return關(guān)鍵詞 返回的一個(gè)undefined的值
函數(shù)執(zhí)行過程
1.把對應(yīng)的開辟的function內(nèi)存里面的代碼塊丟給方法棧(執(zhí)行棧)去執(zhí)行
2.執(zhí)行棧就會(huì)自動(dòng)取執(zhí)行對應(yīng)的方法 執(zhí)行完返回對應(yīng)的結(jié)果
3.當(dāng)前結(jié)果返回完畢以后 對應(yīng)的執(zhí)行棧里面的內(nèi)存空間要進(jìn)行回收(GC)將這個(gè)內(nèi)存空間銷毀
函數(shù)作用域
作用域
當(dāng)前一個(gè)變量的作用范圍 分為局部作用域(在一個(gè)函數(shù)內(nèi)聲明的 或者是在一段代碼塊內(nèi)聲明的 他的作用范圍就是當(dāng)前的代碼塊)和全局作用域(在對應(yīng)的全局聲明的 他的作用范圍就是全局的)
作用域鏈
當(dāng)前的作用域內(nèi)沒有找到對應(yīng)的變量就會(huì)向上去尋找 而這個(gè)過程構(gòu)成的鏈?zhǔn)浇Y(jié)構(gòu)稱為作用域鏈
var a = 20
function fn(){
console.log(a);//undefined 沒有var關(guān)鍵詞就20
//優(yōu)先在同級去找 var a 在 function聲明會(huì)一起聲明肺樟,但未賦值脐供,初始值是undefined.
var a = 10
if(10>9){
console.log(a);//undefined 沒有var關(guān)鍵詞就10
var a = 30
if(5>4){
console.log(a);//undefined 沒有var關(guān)鍵詞就30
var a = 40
if(a>10){
console.log(a);//40
}
}
}
}
fn()
函數(shù)的arguments(參數(shù)數(shù)組 參數(shù)的集合)
arguments是一個(gè)偽數(shù)組(有部分的數(shù)組特性)(可以通過length屬性對應(yīng)的長度 [] 下標(biāo)來訪問里面的元素)
function sum(){ //不清楚參數(shù)個(gè)數(shù)(無參)
// arguments 可以接收里面所有的參數(shù)
//獲取里面?zhèn)鬟f的所有的參數(shù) arguments 長度length
//下標(biāo)索引是從0開始的
var result = 0
//遍歷對應(yīng)的arguments里面的所有的參數(shù)
for(var i=0;i<arguments.length;i++){
result += arguments[i] //取出里面的參數(shù)進(jìn)行求和
}
return result
}
所有的函數(shù)都具備arguments (對象)
訪問
length屬性訪問長度
[] 加下標(biāo)(從0開始)訪問里面的元素
函數(shù)的嵌套
函數(shù)的嵌套: 函數(shù)內(nèi)部可以再包含其他函數(shù);
-
函數(shù)之間允許相互調(diào)用趣钱,也允許向外調(diào)用, 但是不可以調(diào)用同級函數(shù)的嵌套函數(shù);
function fn1(){ console.log('函數(shù)1'); function fn2(){ console.log('函數(shù)2'); // fn1() 沒有結(jié)束就是死循環(huán) } function fn3(){ console.log('函數(shù)3'); //調(diào)用函數(shù)2 fn2() } fn2() fn3() } fn1() //函數(shù)1 函數(shù)2 函數(shù)3 函數(shù)2
遞歸算法
遞歸可以完成所有循環(huán)做的事情 (但是遞歸的效率較低)
遞歸三要素
找規(guī)律
找臨界值(沒有規(guī)律的值)return
自己調(diào)自己(在函數(shù)內(nèi)部調(diào)用自己的函數(shù))
1) 2 4 6 8 10 第100的值是什么
function fn(n){ //一般情況都會(huì)有參數(shù) n表示為位數(shù)
if(n==1){//沒規(guī)律的(一般在前面或者后面)
return 2 //返回具體的值
}else{ //有規(guī)律的 返回對應(yīng)的規(guī)律的公式
return fn(n-1)+2
}
}
console.log(fn(100))
2)1 3 6 10 15 21 第100位 前一位+對應(yīng)的位數(shù) = 這個(gè)一位的值
function fn1(n){
if(n==1){
return 1
}else{
return fn1(n-1)+n
}
}
console.log(fn1(6));
3) 1 2 3 5 8 13 21 第100位值(遞歸的效率極低 一般不使用遞歸 不推薦 (文件的遍歷 菜單遍歷 深拷貝))
function fn2(n){
if(n==1){
return 1
}else if(n==2){
return 2
}else{
return fn2(n-2)+fn2(n-1)
}
}
console.log(fn2(7));