Search K
Appearance
Appearance

- 为什么需要函数?
- 可以实现代码复用,提高开发效率
- 函数是什么?
- function 设计为执行特定任务的代码块
函数:function,是被设计为执行特定任务的代码块
说明:函数可以把具有相同或相似逻辑的代码 " 包裹 " 起来,通过函数调用执行这些被 " 包裹 " 的代码逻辑,这么做的优势是有利于精简代码方便复用。
比如我们前面使用的 alert() 、 prompt() 和 console.log() 都是一些 js 函数,只不过已经封装好了,我们直接使用的。
作用:
- 函数是用那个关键字声明的?
- function
- 函数不调用会执行吗?如何调用函数?
- 函数不调用自己不执行
- 调用方式:
函数名()- 函数的复用代码和循环重复代码有什么不同?
- 循环代码写完即执行,不能很方便控制执行位置
- 随时调用,随时执行,可重复调用
// 声明关键字 函数名 形式参数列表
function functionName(parameter1, parameter2, parameterN) {
// 函数体
return result;
}
- 和变量命名基本一致
- 尽量小驼峰式命名法
- 前缀应该为动词
- 命名建议:常用动词约定
addNumbers。如果函数名称由多个单词组成,则可以使用下划线或破折号来分隔单词,例如 calculate_area 或 show-alert。| 动词 | 含义 |
|---|---|
| can | 判断是否可执行某个动作 |
| has | 判断是否含义某个值 |
| is | 判断是否为某个值 |
| get | 获取某个值 |
| set | 设置某个值 |
| load | 加载某些数据 |
function getName() {}
function addSquares() {}JavaScript 函数可以通过函数名称来调用。调用函数时需要指定函数的参数列表(如果该函数需要参数)。
functionName(arg1, arg2, arg3, ..., argN);
// 如果要调用一个名为 addNumbers 的函数,并将数字 3 和 4 作为参数传递给它
addNumbers(3, 4);
// 将 addNumbers 函数的返回值赋值给变量 sum
var sum = addNumbers(3, 4);functionName 是函数名称,arg1 到 argN 是传递给函数的参数列表,用逗号分隔。我们曾经使用的 alert() , parseInt() 这种名字后面跟小括号的本质都是函数的调用。
注意
() 调用函数。函数体是函数的构成部分,它负责将相同或相似代码 " 包裹 " 起来,直到函数调用时函数体内的代码才会被执行。
函数的功能代码都要写在函数体当中。
需求:
// 打招呼的函数 hi~
function sayHi(name) {
console.log(`Hi, ${name}!`);
}
sayHi("Tom"); // 输出 Hi, Tom!
// 把 99 乘法表封装到函数里面,重复调用 3 次
function multiplicationTable() {
for (let i = 1; i <= 9; i++) {
let row = "";
for (let j = 1; j <= i; j++) {
row += `${j}*${i}=${i * j}\t`;
}
console.log(row);
}
}
for (let i = 0; i < 3; i++) {
multiplicationTable();
}需求:
// 封装一个函数,计算两个数的和
function sum(a, b) {
return a + b;
}
console.log(sum(2, 3)); // 输出 5
// 封装一个函数,计算 1-100 之间所有数的和
function sumOfNumbers() {
let sum = 0;
for (let i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
console.log(sumOfNumbers()); // 输出 5050
- 函数传递参数的好处是?
- 可以极大的提高了函数的灵活性
- 函数参数可以分为那两类?怎么判断他们是那种参数?
- 函数可以分为形参和实参
- 函数声明时,小括号里面的是形参,形式上的参数
- 函数调用时,小括号里面的是实参,实际的参数
- 尽量保持形参和实参的个数一致
- 参数中间用什么符号隔开?
- 逗号
声明(定义)一个功能为打招呼的函数
通过向函数传递参数,可以让函数更加灵活多变,参数可以理解成是一个变量。
, 分隔// x, y 形参
function addNumbers(x, y) {
return x + y;
}
// 3, 4 实参
let result = addNumbers(3, 4);
console.log(result); // 输出 7alert('打印'), parseInt('11'), Number('11') 本质上都是函数调用的传参。注意
undefined。需求:采取函数封装的形式:输入 2 个数,计算两者的和,打印到页面中
function getSum(a, b) {
document.write(a + " + " + b + " = " + (a + b));
}
let num1 = +prompt("请输入第一个数");
let num2 = +prompt("请输入第二个数");
getSum(num1, num2);形参可以看做变量,但是如果一个变量不给值,默认是 undefined。
但是如果做用户不输入实参,刚才的案例,则出现 undefined + undefined 结果是 NaN。
我们可以改进下,用户不输入实参,可以给 形参默认值,可以默认为 0, 这样程序更严谨,可以如下操作:
function getSum(a = 0, b = 0) {
return a + b;
}
getSum(); // 输出为 0,而不是 NaN
getSum(1, 2); // 输出为 3注意
函数形参默认值只会在缺少实参参数传递时 才会被执行,所以有参数会优先执行传递过来的实参,否则默认为 undefined。
// 封装一个求和函数,形参是一个数组
function sum(nums) {
let total = 0;
// 函数内部遍历数组求和
for (let i = 0; i < nums.length; i++) {
total += nums[i];
}
return total;
}
let scores = [
[80, 90, 70],
[75, 95, 85],
[90, 80, 85],
];
for (let i = 0; i < scores.length; i++) {
// 传递过去的参数是一个数组
let studentTotal = sum(scores[i]);
console.log(`Student ${i + 1} total score: ${studentTotal}`);
}
// Student 1 total score: 240
// Student 2 total score: 255
// Student 3 total score: 255
- 函数很多情况下需要返回值
- 为什么要让函数有返回值
- 函数执行后得到结果,结果是调用者想要拿到的(一句话,函数内部不需要输出结果,而是返回结果)
- 对执行结果的扩展性更高,可以让其他的程序使用这个结果
- 函数有返回值用那个关键字?有什么注意事项呢?
- 语法:return 数据
- return 后面不接数据或者函数内不写 return,函数的返回值是 undefined
- return 能立即结束当前函数,所以 return 后面的数据不要换行写
return 这个关键字,将内部执行结果传递到函数外部,这个被传递到外部的结果就是返回值。function addNumbers(x, y) {
return x + y;
}
let result = addNumbers(3, 4);
console.log(result); // 输出 7
// 当然,我们也可以直接使用函数调用表达式,而不是先将结果存储在变量中。
console.log(addNumbers(3, 4)); // 输出 7总结
求任意 2 个数中的最大值,并返回。
function getMaxNum(num1, num2) {
return num1 > num2 ? num1 : num2;
}
console.log(getMaxNum(5, 9)); // 输出 9求任意数组中的最大值并返回这个最大值。
function getMaxInArray(arr) {
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
console.log(getMaxInArray([5, 9, 3, 7, 6])); // 输出 9求任意数组中的最小值并返回这个最小值。
function getMinInArray(arr) {
let min = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
return min;
}
console.log(getMinInArra([5, 9, 3, 7, 6])); // 输出 3断点调试:进入函数内部看执行过程 F11
两个相同的函数后面的会覆盖前面的函数
在 Javascript 中 实参的个数和形参的个数可以不一致
undefined (了解即可)函数一旦碰到 return 就不会在往下执行了 函数的结束用 return
break 和 return 都可以用来结束代码块的执行。
switch 语句中的执行,并跳出该语句。function findIndex(arr, value) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === value) {
return i; // 如果找到了值,返回下标并结束函数的执行
}
}
return -1; // 如果未找到值,则返回 -1 并结束函数的执行
}
let numbers = [3, 6, 9, 12, 15];
let index = findIndex(numbers, 12);
console.log(index); // 输出 3注意
- JS 中作用域分为哪 2 种?
- 全局作用域。函数外部或者整个 script 有效
- 局部作用域。也称为函数作用域,函数内部有效
- 根据作用域不同,变量分为哪 2 种?
- 全局变量
- 局部变量
- 有一种特殊情况是全局变量是那种?我们提倡吗?
- 局部变量或者块级变量 没有 let 声明直接赋值的当全局变量看
- 我们强烈不提倡
- 还有一种特殊情况,函数内部的形参可以当做局部变量看
- 变量访问原则是什么?
- 采取就近原则的方式来查找变量最终的值
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
作用于所有代码执行的环境 (整个 script 标签内部) 或者一个独立的 js 文件
处于全局作用域内的变量,称为全局变量
作用于函数内的代码环境,就是局部作用域。因为跟函数有关系,所以也称为函数作用域。
处于局部作用域内的变量称为局部变量
变量特殊情况
如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
但是有一种情况,函数内部的形参可以看做是局部变量。
作用域链:采取就近原则的方式来查找变量最终的值。
function f1() {
let num = 123; // num
function f2() {
let num = 0; // 就近 num
console.log(num); // num 输出 0
}
f2();
}
let num = 456;
f1();let a = 1; // a
function fn1() {
let a = 2; // a
let b = "22"; // 就近 b
fn2();
function fn2() {
let a = 3; // a
fn3();
function fn3() {
let a = 4; // 就近 a
console.log(a); // a 的值 4
console.log(b); // b 的值 22
}
}
}
fn1();
- 立即执行函数有什么作用?
- 防止变量污染
- 立即执行函数需要调用吗?有什么注意事项呢?
- 无需调用,立即执行,其实本质已经调用了
- 多个立即执行函数之间用分号隔开
函数可以分为具名函数和匿名函数。
具名函数:具名函数是指在函数定义时为函数指定一个名称。
function add(x, y) {
return x + y;
}
// 通过函数名调用该函数
let result = add(2, 3);
console.log(result); // 输出 5匿名函数:匿名函数是指在函数定义时不指定函数名称的函数。这种函数通常作为参数传递给其他函数或被赋值给变量。
let add = function(x, y) {
return x + y;
};
// let result = add(2, 3);
console.log(result); // 输出 5注意
除非将匿名函数赋值给变量或作为参数传递给其他函数,否则它们将不会被执行。
function sayHello() {
// 定义了一个匿名函数,但由于未调用该函数,它不会执行任何操作
let greeting = function () {
console.log("Hello!");
};
}
// 如果想要执行该匿名函数,可以添加一对括号来调用它
function sayHello() {
let greeting = function () {
console.log("Hello!");
};
greeting(); // 调用匿名函数并输出 "Hello!"
}let add = function (x, y) {
return x + y;
};
// 通过变量名来调用匿名函数
let result = add(2, 3);
console.log(result); // 输出 5let sortFunc;
if (userSortPreference === "ascending") {
// 根据用户的排序偏好创建一个函数表达式,并将其赋值给变量 sortFunc
sortFunc = function (a, b) {
return a - b;
};
} else {
// 根据用户的排序偏好创建一个函数表达式,并将其赋值给变量 sortFunc
sortFunc = function (a, b) {
return b - a;
};
}
// 使用该函数来对数组进行排序
array.sort(sortFunc);立即执行函数是一个自我执行的匿名函数,它在定义后立即被执行。
立即执行函数通常用于初始化代码或创建私有作用域。当我们需要一些代码在加载时立即执行时,可以使用立即执行函数来实现。
场景介绍:避免全局变量之间的污染。可以避免在全局命名空间中创建不必要的变量,并且可以确保匿名函数不会与其他代码发生冲突。
(function () {
console.log("Hello, world!");
})();<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Immediate Function Demo</title>
<script>
// 定义了一个立即执行函数
(function () {
// 设置了一个名为 globalVar 的变量
let globalVar = "Hello, world!";
// 将其赋值给全局对象的 myGlobalVar 属性
window.myGlobalVar = globalVar; // 将变量赋值给全局对象
})();
</script>
</head>
<body>
<h1>Welcome to my website!</h1>
<!-- 在页面加载时,我们可以使用 <%=myGlobalVar%> 语法将变量的值插入到 HTML 中。 -->
<p>The value of my global variable is: <%=myGlobalVar%></p>
</body>
</html>注意
多个立即执行函数要用 ; 隔开,要不然会报错。
h = parseInt(总秒数 / 60 / 60 % 24) m = parseInt(总秒数 / 60 % 60 )s = parseInt(总秒数 % 60)<h1>转换时间</h1>
<form>
<label for="seconds-input">总秒数</label>
<input type="number" id="seconds-input" name="seconds" />
<button type="button" onclick="handleInput()">转换</button>
</form>
<p>The time is: <span id="output">00:00:00</span></p>function addZero(num) {
return (num < 10 ? "0" : "") + num;
}
function convertSecondsToTime(seconds) {
let h = parseInt((seconds / 60 / 60) % 24);
let m = parseInt((seconds / 60) % 60);
let s = parseInt(seconds % 60);
return addZero(h) + ":" + addZero(m) + ":" + addZero(s);
}
function handleInput() {
let secondsInput = document.getElementById("seconds-input");
let output = document.getElementById("output");
let seconds = parseInt(secondsInput.value || Math.floor(Math.random() * 3600 * 24));
let timeString = convertSecondsToTime(seconds);
output.innerHTML = timeString;
secondsInput.value = "";
}