函数
定义:
函数: function,是被设计为执行特定任务的代码块,可以实现代码复用,提高开发效率
**说明:**函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。
函数使用
①声明语法
function 函数名(){
函数体
}
例:
function sayHi(){
console.log('hai~~')
}
②函数名命名规范
- 和变量命名基本一致
- 尽量小驼峰式命名法
- 前缀应该为动词
- 命名建议:常用动词约定
function getName() {}
function addSquares() {}
③调用语法
-
注意:声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数
-
我们曾经使用的 alert() , parseInt() 这种名字后面跟小括号的本质都是函数的调用
函数名()
<script>
//函数声明
function sayHi() {
document.write('早上好');
document.write('中午好');
document.write('晚上好');
}
//函数调用
sayHi();
sayHi();
</script>
④函数体
函数体是函数的构成部分,它负责将相同或相似代码“包裹”起来,直到函数调用时函数体内的代码才会被执行。函数的功能代码都要写在函数体当中。
function sayHi(){
console.log('嗨~'); //函数体
}
sayHi()
⑤封装函数案例
<script>
//需求:把99乘法表封装到函数里面,重复调用3次
function multiplication() {
for (let index = 1; index <= 9; index++) {
for (let index1 = 1; index1 <= index; index1++) {
let num = index1 * index;
document.write(`<span> ${index1} * ${index} = ${num} </span>`);
}
document.write('<br/>');
}
}
multiplication();
multiplication();
multiplication();
</script>
函数传参
①函数声明
参数列表
- 传入数据列表
- 声明这个函数需要传入几个数据
- 多个数据用逗号隔开
function 函数名 (参数列表){
函数体
}
②函数调用
调用函数时,需要传入几个数据就写几个,用逗号隔开
函数名(传递的参数列表)
③形参和实参
- 形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
- 实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
- 形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值
- 开发中尽量保持形参和实参个数一致
- 我们曾经使用过的 alert('打印'), parseInt('11'), Number('11') 本质上都是函数调用的传参
④语法及案例
例:可单个参数,也可以多个参数
<script>
//形参
function getSum(num1, num2) {
console.log(num1 + num2);
}
//实参
getSum(11, 22);//调用语法
getSum(66, 66);
getSum(99, 99);
</script>
<script>
//需求:学生的分数是一个数组,计算每个学生的总分
// let arr1 = [];
// let arr2 = [];
function getSum(arr) {
let sum =0;
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
}
console.log(sum);
}
let arr1 = [11, 22, 33, 44, 55, 66, 77];
let arr2 = [12, 432, 66, 77, 99, 22, 55]
getSum(arr1);
getSum(arr2);
</script>
函数返回值
①为什么要让函数有返回值
有些函数没有返回值的话:
-
缺点:把计算后的结果处理方式写死了,内部处理了
-
解决:把处理结果返回给调用者
-
l所以要根据需求,来设定需不需要返回值
有返回值函数的概念:
- 当调用某个函数,这个函数会返回一个结果出来
- 这就是有返回值的函数
②用return返回数据
- 当函数需要返回数据出去时,用return关键字
<script>
// function getMax() {}
// function getSum() {}
// // 这个num1 就是 函数getMax调用的返回值 ( num1 = 1 2 。。)
// // let num2 = getSum();
// let num1 = getMax();// 我们自己写的函数 只能返回 undefined
// let num3 = parseInt(1.3);// js自己内部写的 返回值 1
// console.log(num3); //
function getMax() {
// 100 就是 函数在执行完毕的时候 会返回的数据
return 300;
}
let num1 = getMax(); // num1 =100
console.log(num1);
</script>
③细节:
- 在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
- 函数内部只能运行到 1 次 return,并且 return 后面代码不会再被执行,所以 return 后面的数据不要换行写
- return会立即结束当前函数
- 函数可以没有 return ,这种情况函数默认返回值为 undefined
作用域
①作用域概述
- 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
Ⅰ、全局作用域
- 范围:全局有效
- 作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
Ⅱ、局部作用域
- 局部有效
- 作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域
Ⅲ、块级作用域
- {}内有效
- 块作用域由 { } 包括,if语句和for语句里面的{ }等
<script>
// script标签内的运行环境就是全局作用域
let num = 100; // 全局作用域
function getMax() {
// 这个区域内就不属于全局作用域
// 局部作用域 或者 也叫做 函数作用域
let num2 = 200;
}
for (let index = 0; index < 4; index++) {
// 块级作用域
}
while (true) {
// 块级作用域
}
if (true) {
// 块级作用域
}
</script>
②变量的作用域
- 在JavaScript中,根据作用域的不同,变量可以分为
Ⅰ、全局变量
- 函数外部let 的变量
- 全局变量在变量定义之后区域可以访问和修改
<script>
// 直接写在全局作用域下的变量 = 全局变量 在任意的地方来访问
let num = 100; // 全局变量 在任何地方都可以访问
function getMax() {
console.log('函数 访问全局变量', num);
}
getMax();
for (let index = 0; index < 2; index++) {
console.log('for循环内 块级作用域 访问全局变量', num);
}
if(true){
console.log("if语句 也 可以访问全局变量",num);
}
</script>
全局变量补充:
- 定义一个变量 没使用 let 关键字 那么它就是一个全局变量
- 都建议 定义变量的时候 都要记得使用let ,不用去记这么规则
<script>
// userName = '索隆';
// console.log(userName);
function func1() {
// userName = '索隆'; // 全局变量 没有使用let 关键字
let userName = '索隆'; // 局部变量
}
func1();
console.log(userName); // 报错
</script>
Ⅱ、局部变量
- 函数内部let的变量
- 局部变量只能在当前函数内部访问和修改
<script>
// 局部变量
// 如果是在函数内部定义的变量 就叫做局部变量
// 局部变量 不能在 它的大括号之外使用的,否则就会报错!!
let msg = 10000; // 全局变量
// 局部变量 函数内部 声明的变量
function getMax() {
// 声明一个数字
let num = 200; // 局部变量
}
// 局部变量 不能在 超出它的大括号来使用
console.log(num); // 会报错
</script>
Ⅲ、块级变量
- {} 内部的let变量
- let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问
<script>
// 块级变量 就是我们在块级作用域内 定义的变量
// 块级变量 类似局部变量,也是超出了自身的大括号 不能使用
// for (let index = 0; index < 2; index++) {
// // num 块级变量
// let num = 100;
// }
// console.log(num);// 使用块级变量 出错!!
// {
// let num =10;
// }
// {
// console.log(num);
// }
</script>
Ⅳ、变量作用域特殊情况:
- 如果函数内部或者块级作用域内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
- 函数内部的形参可以看做是局部变量,所以形参相当于函数内部定义的局部变量,只有在函数内部可以使用
Ⅴ、小结
-
分类 分成两类:
① 全局变量 直接放在 script标签内的变量 ②局部变量 用大括号包起来的变量 函数内部变量 块级变量
函数的嵌套使用
<script>
function func1() {
console.log('func1');
func2();
}
function func2() {
console.log('func2');
func3();
}
function func3() {
console.log('func3');
}
func1(); // 输出什么 1
</script>
作用域链
- 只要是代码,就至少有一个作用域
- 写在函数内部的局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
- 作用域链:根据函数的定义采取就近原则的方式来查找变量最终的值(不是根据函数的调用)
<script>
// let num = 100;
// function func1() {
// let num = 200;
// fun2();
// }
// function fun2() {
// let num = 300;
// console.log(num); // 300
// }
// func1();
// 判断当前变量 输出是什么
// 就近原则 判断是要根据 函数的定义 来判断 而不是函数的调用
// 函数的定义 代码位置来判断 100 这个!!
let num = 100;
function func1() {
let num = 200;
// 函数的调用
fun2();
}
// 函数的定义-声明
function fun2() {
console.log(num);
}
func1();
</script>
匿名函数(了解)
函数分为:
-
具名函数
声明:function fn() {}
调用:fn()
-
匿名函数:
function() {}
匿名函数:将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式
语法与调用:
函数的形参和实参使用跟具名函数一致
//声明
let fn = function () {
函数体
}
//调用
fn()//函数名
// 匿名函数
function () {
// 设置 页面的标题 = 月薪过万
document.title = '月薪过万';
// 设置 页面的背景颜色 = 黄色
document.body.style.backgroundColor = 'yellow';
}
自执行函数(了解)
-
避免全局变量之间的污染
-
注意: 多个立即执行函数要用 ; 隔开,要不然会报错
-
适合做一次性的任务- 不希望这个函数可以得到复用!!! 函数包装多段代码 让程序比较简洁
语法:
//方式1
(function () { console.log(11)})();
//方式2
(function () { console.log(11)}());
//不需要调用,立即执行
//1 页面打开时候
//1 设置 页面的标题 = 月薪过万
//2 设置 页面的背景颜色 = 黄色
let msg = 123;
// 自执行函数
(function () {
let msg = 123;
// 设置 页面的标题 = 月薪过万
document.title = '月薪过万';
// 设置 页面的背景颜色 = 黄色
document.body.style.backgroundColor = 'yellow';
})();
console.log(msg);