文章目录
- 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)