函數函數概述函數 實際就是多行代碼的抽取(多行代碼會構成特定的功能)(方法)函數的優點減少冗餘代碼(重覆的代碼放在函數裡面 在需要的時候調用)函數封裝(特定的一些代碼使用函數來包起來),提高了代碼的可維護性及可閱讀性函數的分類1.系統函數 window裡面的所有函數都屬於系統函數 (console. ...
函數
函數概述
函數 實際就是多行代碼的抽取(多行代碼會構成特定的功能)(方法)
函數的優點
減少冗餘代碼(重覆的代碼放在函數裡面 在需要的時候調用)函數封裝(特定的一些代碼使用函數來包
起來),
提高了代碼的可維護性及可閱讀性
函數的分類
1.系統函數 window裡面的所有函數都屬於系統函數 (console.log() alert() prompt()...)
2.內置函數 所有的內置對象裡面的函數 都叫內置函數 (Math.pow())
3.自定義函數( 自己定義的函數)
內置函數和系統函數我們更關註於他的使用 自定義函數(定義以及使用)
1.使用function關鍵詞 定義匿名函數(沒有名字的函數)(個人感覺用途不是很廣,因為,他沒有復用價值,只能一次一次的用)
function(形參(可以省略的 可以有多個)){ 函數體(代碼) } //直接調用 讓別人(事件)去調用(自動調用) (function(){ console.log('匿名函數') })()
2.使用function關鍵詞 定義具名函數 (有名字的函數)(聲明試,有名字,可以隨便調用)
function 函數名(形參,形參...){ 函數體(代碼) } //聲明 具名函數(第一種) function sayHello(){ console.log('hello') } sayHello() //傳遞參數 function sayHello1(name,age){ //形參是形容的參數 console.log('hello'+name+age) } sayHello1('李四') //傳進的是實參 根據你要的參數個數來傳遞對應的參數個數 //調用 // sayHi() //報錯 // console.log(sayHi); undefined //具名函數的變種聲明 (第二種) var sayHi = function(){ console.log('hi') } sayHi()
3.使用new Function方式(賦值法)
var 函數名 = new Function('形參,形參1','函數體') //定義 var sayBye = new Function('console.log("bye bye!!")') //調用 sayBye() //傳參 var sayBye = new Function('username','console.log("bye bye!!"+username)') //調用 sayBye('李四')
在程式執行之前有個預編譯過程
預編譯
1.他會聲明對應的function和var關鍵詞修飾的變數(開闢記憶體的操作)
2.對應的function的記憶體空間開闢以後他會將對應的代碼塊放到其中 等待調用
3.var 修飾的關鍵詞 只會開闢一個空間 並不會進行賦值(預設給他的一個undefined的值)
return
return 返回對應的數據的 他是在函數內容進行數據返回的(當你調用了return操作後 後面的內容將不
再執行)即:只要有return他就會跳出來,不會在執行後面的相關程式了!
function sum(a,b){ return a+b console.log('不會執行的代碼') } console.log(sum(1,2))//返回的對應的1+2的結果
如果沒有return關鍵詞 返回的一個undefined的值,因為你沒有返回值,所以沒有返回值,所以sayHi裡面啥也沒有所以會輸出undefined
function sayHi(){ console.log('hi') } console.log(sayHi()) //undefined
函數執行過程
1.把對應的開闢的function記憶體裡面的代碼塊丟給方法棧(執行棧)去執行
2.執行棧就會自動取執行對應的方法 執行完返回對應的結果
3.當前結果返回完畢以後 對應的執行棧裡面的記憶體空間要進行回收(GC)將這個記憶體空間銷毀
函數作用域
作用域
當前一個變數的作用範圍 分為局部作用域(在一個函數內聲明的 或者是在一段代碼塊內聲明的 他的作
用範圍就是當前的代碼塊)和全局作用域(在對應的全局聲明的 他的作用範圍就是全局的)
作用域鏈(個人理解往上面找,找爸爸借錢,不找兒子借錢)
var a = 20 function fn(){ console.log(a);//undefined 沒有var關鍵詞就20 var a = 10 if(10>9){ console.log(a);//undefined 沒有var關鍵詞就10 var a = 30 if(5>4){ console.log(a);//undefined 沒有var關鍵詞就30 var a = 40 if(a>10){ console.log(a);//40 } } } } fn()
函數的arguments(參數數組 參數的集合)
arguments是一個偽數組(有部分的數組特性)(可以通過length屬性對應的長度 [] 下標來訪問裡面的
元素)(個人理解:即有數組的性質但是,不是數組)
function sum(){ //不清楚參數個數(無參) // arguments 可以接收裡面所有的參數 //獲取裡面傳遞的所有的參數 arguments 長度length //下標索引是從0開始的 var result = 0 //遍歷對應的arguments裡面的所有的參數 for(var i=0;i<arguments.length;i++){ result += arguments[i] //取出裡面的參數進行求和 } return result }
所有的函數都具備arguments (對象)
訪問
1.length屬性訪問長度
2.[] 加下標(從0開始)訪問裡面的元素
函數的嵌套
函數的嵌套: 函數內部可以再包含其他函數;
函數之間允許相互調用,也允許向外調用, 但是不可以調用同級函數的嵌套函數;
(個人理解:能給自己兒子借錢,可以給朋友借錢,但是不能給朋友的兒子借錢)
function fn1(){ console.log('函數1'); function fn2(){ console.log('函數2'); // fn1() 沒有結束就是死迴圈 } function fn3(){ console.log('函數3'); //調用函數2 fn2() } fn2() fn3() } fn1() //函數1 函數2 函數3 函數2
註意事項
函數的抽取 (抽取冗餘的代碼)
1.參數 (可變的內容)
2.返回值 (我們想從這個函數得到什麼)
Dom的簡單操作
1.獲取對應的標簽 (通過id獲取)
document.getElementById('id的屬性值')
2.input框的值獲取 value屬性
document.getElementById('input框的id').value //得到input框內的值
3.點擊事件 onclick
element.onclick = function(){ //相關操作 }
示例(以事件做為驅動)
//通過輸入框輸入數值判斷對應的奇偶並列印 <input id="number" type="text"> <button id="btn">判斷奇偶</button> <script> function handlerClick(){ //拿到input框裡面的內容 獲取到input框 var inputValue = document.getElementById('number').value //string類型 // console.log(typeof inputValue); 如果是+法操作必須要先轉類型 //判斷奇偶的操作 if(inputValue%2==0){ console.log('當前為偶數'); }else{ console.log('當前為奇數'); } } //首先需要點擊按鈕 獲取按鍵 加點擊事件 //事件觸發自動調用對應的函數 (事件驅動) document.getElementById('btn').onclick = handlerClick </script>
遞歸演算法*
遞歸可以完成所有迴圈做的事情 (但是遞歸的效率較低)
遞歸三要素
1.找規律
2.找臨界值(沒有規律的值)return
3.自己調自己(在函數內部調用自己的函數)
2 4 6 8 10 第100的值是什麼
function fn(n){ //一般情況都會有參數 n表示為位數 if(n==1){//沒規律的(一般在前面或者後面) return 2 //返回具體的值 }else{ //有規律的 返回對應的規律的公式 return fn(n-1)+2 } } console.log(fn(100))
示例
// 1 3 6 10 15 21 第100位 前一位+對應的位數 = 這個一位的值 function fn1(n){ if(n==1){ return 1 }else{ return fn1(n-1)+n } } console.log(fn1(6)); // 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));
bfs 廣度優先搜索 dfs 深度優先搜索(遞歸思想)
作業::遞歸
//第8題 兔子繁殖問題,設有一隻新生兔子,從第四個月開始他們每個月, 月初都生一隻兔子, 新生的兔子從第四個月月初開始又每個月生一隻兔子按此規律,並假定兔子沒有死亡, n(n<=20)個月月末共有多少只兔子? function fn6(n) { if (n <= 3) { return 1 } else { return fn6(n-1)+fn6(n-3) } } console.log(fn6(11)); //3天就可以生一個兔子兔子後面可以一天生一個 function fn7(n){ if(n<=2){ return 1 }else{ return fn7(n-1)+fn7(n-2) } } console.log(fn7(10));
兔子繁殖問題,設有一隻新生兔子,從第四個月開始他們每個月, 月初都生一隻兔子, 新生的兔子從第四個月月初開始又每個月生一隻兔子按此規律,並假定兔子沒有死亡, n(n<=20)個月月末共有多少只兔子?(題目解釋,有過程)
function fn6(n) { if (n <= 3) { return 1 } else { return fn6(n-1)+fn6(n-3) } } console.log(fn6(11)); //第一列表示月數 第一行表示當前月份中各個月份的兔子的數量 // 1 2 3 4 //1 1 0 0 0 1 //2 0 1 0 0 1 //3 0 0 1 0 1 //4 1 0 0 1 2 //註意這個是第一個兔子生孩子了,所以會有一個還在一月份的兔子 //5 1 1 0 1 3 //6 1 1 1 1 4 //7 2 1 1 2 6//第二個兔子也可以生孩子了 //8 3 2 1 3 9 //9 4 3 2 4 13 //10 6 4 3 6 19 找規律的f(m) = f(n-1) + f(n-3) 然後掏遞歸公式咯,一下就出來了
今天的總結完畢咯!!