文章目錄
- 1、函數的聲明與調用
- 2、形參默認值
- 3、函數的返回值
- 4、變量的作用域
- 5、變量的訪問原則
- 6、匿名函數
- 6.1 函數表達式
- 6.2 立即執行函數
- 7、練習
- 8、邏輯中斷
- 9、轉為布爾型

1、函數的聲明與調用
function 函數名(形參列表) {函數體
}
eg:
// 聲明
function sayHi() {console.log('Hello World!')
}// 調用
sayHi()
注意:
-
形參不需要帶類型
-
兩個相同的函數后面的會覆蓋前面的函數
-
參的個數和形參的個數可以不一致,形參過多,默認給undefined,實參過多,多余的實參會被忽略 (函數內部有一個arguments,里面裝著所有的實參)
命名規范:
- 和變量命名基本一致
- 盡量小駝峰式命名法
- 前綴應該為動詞
2、形參默認值
<body><script>function getSum(num1, num2) {document.write(num1 + num2)}// 3getSum(1, 2)// NaNgetSum()</script>
</body>
如上,形參不傳值,計算結果是NaN,形參也是一個變量,不給值,則是undefined,undefined + unfined = NaN,改進下:
function getSum(num1 = 0, num2 = 0) {document.write(num1 + num2)
}
形參默認值只會在缺少實參參數傳遞時才會被執行
// 練習:數組求和函數
<body><script>function getArrSum(array = []) {let sum = 0for (let i = 0; i < array.length; i++) {sum = sum + array[i]}console.log(sum)}getArrSum([1, 2, 3, 4, 5])getArrSum()</script>
</body>
3、函數的返回值
function getSum(num1, num2) {return num1 + num2
}
- return結果給調用者
- return 后面代碼不會再被執行
- return函數可以沒有return語句,此時,默認返回undefined
function getSum(num1, num2) {num1 + num2
}// 調用一個沒有返回結果的函數,查看調用結果
console.log(getSum(1, 2)) //undefined
練習: 求一個數組的最大值
<body><script>function getMax(array = []) {let max = array[0]for (let i = 1; i < array.length; i++) {if (max < array[i]) {max = array[i]}}return max}console.log(getMax([1, 3, 4, 6, 9]))</script>
</body>
4、變量的作用域
作用域:
對應的,變量分為:全局變量和局部變量
<body><script>// 全局變量let num = 0// 函數中可以用function getNum() {return num}// 函數外面也能用console.log(num)</script>
</body>
<body><script>function doSome() {// 局部變量let i = 1return i}// 局部變量,函數外不可用,報錯i is not definedconsole.log(i)</script>
</body>
最后,作用域有一個坑:如果函數內部,變量沒有聲明,直接賦值,也當全局變量看,但是強烈不推薦
<body><script>function doSome() {// 不聲明,直接賦值num = 1}// 調用一下doSome()// 1,訪問成功console.log(num)</script>
</body>
5、變量的訪問原則
如下,輸出是20,首先兩個num作用域不同,并不沖突,其次,console.log打印時,num就近
訪問原則:
- 在能夠訪問到的情況下 先局部, 局部沒有在找全局,遵循就近原則
- 如果函數中還有函數,那么在這個作用域中就又可以誕生一個作用域
6、匿名函數
函數定義完需要調用,匿名函數沒有名字,因此不能像具名函數一樣通過名字調用,其調用方式有兩種:
- 函數表達式
- 立即執行函數
6.1 函數表達式
語法是將匿名函數賦值給一個變量
<body><script>let fn = function(num) {console.log('函數表達式的方式')}// 調用fn(1)</script>
</body>
這種寫法很像常規的具名函數定義,但有區別:
也就是說,具名函數的調用,可以寫在任何位置,而匿名函數用函數表達式來調用是不行的,因為函數表達式是一個let,最后,匿名函數的使用場景舉例:在Web API中
6.2 立即執行函數
寫法:拿個小括號包著匿名函數,最后再加個空的小括號,第二個小括號是在做調用,因此,這個函數一定義,匿名函數就立馬被執行了,因此,叫立即執行函數
封號也可以寫前面,以下兩種寫法都行:
<body><script>(function () {console.log(1)})();(function () {console.log(2)})();</script>
</body>
// 封號寫前面
<body><script>; (function () {console.log(1)})(); (function () {console.log(2)})()</script>
</body>
立即執行函數還有個作用:防止變量污染
再體會下,上面說的第二個小括號是在做調用
<body><script>(function (x, y) {console.log(x + y)})(1, 3);</script>
</body>
匿名函數的立即執行函數寫法,還有一種寫法,小括號里面包著匿名函數 + 一個空的小括號
最后,多個立即執行函數要用 ; 隔開,要不然會報錯。未來其使用場景如:
立即執行函數也可以有函數名,如下,寫成立即執行函數,一來不用再特地調用,二來,這個JS文件被引入后,即使JS中定義了變量,也不會引起變量污染
7、練習
需求: 用戶輸入秒數,可以自動轉換為時分秒
<body><script>function convertTime(totalSecond = 0) {let hour = parseInt(totalSecond / 60 / 60 % 24)let minute = parseInt(totalSecond / 60 % 60)let second = parseInt(totalSecond % 60)// 補0,讓1小時變成01小時hour = hour < 10 ? '0' + hour : hourminute = minute < 10 ? '0' + minute : minutesecond = second < 10 ? '0' + second : secondreturn `${hour}時${minute}分${second}秒`}let totalSecond = +prompt('輸入總秒數')document.write(convertTime(totalSecond))</script>
</body>
此外,hour = hour < 10 ? '0' + hour : hour
其實也體現了JS的弱類型,hour本身是數字型,最后重新賦值可能是一個String型,也沒報錯
8、邏輯中斷
通過左邊能得到整個式子的結果,因此沒必要再判斷右邊,即短路
// 都是真,返回最后一個真值
console.log(11 && 22) //22//邏輯或,返回最后一個真值
console.log(11 || 22) //11
下面這個寫法,和給形參給默認值,效果一樣,x和y不傳時,為undefined,當false看,做邏輯與,就是0,最后結果為0 + 0
未來短路運算的使用場景:
注意??,和Java不同,JS的短路與和短路或 操作符返回的是操作數的值,而不是布爾值(true 或 false)
9、轉為布爾型
顯示轉換語法:
Boolean(內容)
''、0、undefined、null、false、NaN 轉換為布爾值后都是false, 其余則為 true
console.log(Boolean('hahhah')) //true
console.log(Boolean(0)) //false
console.log(Boolean(NaN)) //false
console.log(Boolean(111)) //true
有了這個前提,再看
// null
console.log(null && 20)
null當false看,那短路,結果是null,注意,返回是null,我沒加Boolean,下面這個返回才是false
//false
console.log(Boolean(null) && 20)