学习js第三天
函数
函数是JS中的引用类型数据之一。
我们之前学习变量的时候 说变量的作用是复用数据。
函数就是一个工具,可以将代码放在里面,随时执行。
注: 函数是一等公民
函数的组成部分
function关键字
、 函数名
、 () 形参列表
、 {} 函数体
函数的定义
函数的定义方式: 函数声明
、 函数表达式
、 构造函数
函数声明: function fun() {}
函数表达式: var fun = function() {}
构造函数(了解): var fun = new Function()
var fun = function() {
console.log("我是函数表达式");
}
function fun1() {
console.log("我是函数声明");
}
fun1();
fun();
js中函数和变量的提升
JS声明提升
指的是浏览器的解析引擎在执行JS代码的时候会把所有的变量和函数声明的函数提升到代码的最开头
变量的提升
console.log(a);// 可以用 但是没有值
var a = 10;
console.log(a); // 正常用 推荐
函数声明的提升
fun();
function fun() {
console.log(11)
}
fun();
函数表达式的提升 本质并没有提升函数 提升的是变量
console.log(fun); // undefined
fun(); // 报错: fun 不是一个函数
var fun = function() {
console.log(22);
}
fun();
我们现在已经知道的函数的知识有:
1 函数的定义
2 函数的调用
函数定义完毕之后,就可以任意次调用
函数声明定义的函数可以在任何地方去调用
函数表达式定义的函数只能在定义之后去调用
预解析
-
JS引擎执行代码的阶段:
-
通读代码
在通读代码阶段,引擎会先查看是否有语法错误,如果有,就报错。如果没有,则在这个过程中,就会将代码中所有的通过var声明的变量和通过function声明的函数提升到代码的最前面。这个提升行为,就是发生在预解析阶段。
-
执行代码
将代码按照规则,一条一条执行。
-
函数的参数
形参列表中,可以放置 形式参数
。简称: 形参
。形参是函数内的变量
只能够在函数内部使用
当函数执行的时候,可以往圆括号内填写数据,这种行为,叫做 传参
, 用于函数运行中使用,这样的参数叫做 实际参数
,简称 实参
。
函数参数的关系
一个函数的形参和实参有一一对应
的关系。
- 当形参比实参多: 多余的形参的值为undefined
function sum(a, b) {
console.log(a);
console.log(b);
}
sum(10); // a是10 b是undefined
- 当形参比实参少: 没有形参接收多余的实参
function sum(a, b) {
console.log(a);
console.log(b);
}
sum(10, 11, 12); // a是10 b是11 12没有形参来接收
return关键字
作用: 该关键字是用于在函数内部 返回内容
并 中止函数执行
的。
// 中止函数执行
function demo() {
console.log(1);
console.log(2);
console.log(3);
return;
console.log(4);
console.log(5);
}
demo(); // 只会输出1 2 3 而不会输出4 5 因为遇见了return
// 返回内容
var a = 10;
var b = 11;
function sum(num1, num2) {
return num1 + num2;
}
// 进行计算
var result = sum(a, b);
// 使用结果
console.log(result); // 21
注:
return
关键字只能够在函数内部出现。
作用域
- 作用域: 规定变量起作用的范围
- 划分规则: 只有全局作用域和函数的私有作用域
- 作用域是根据书写的单词和语法来确定的,所以又叫做词法作用域.
- 所以,通常我们把代码写完,就可以确定每一个作用域的范围.
注: script标签之间是全局作用域 多个script标签共享同一个作用域 但是每一个script标签中的变量 函数,它们的提升,
只能够在本script标签的范围之内
.
注: 浏览器在加载script标签的代码的时候,是一个script标签加载并执行完毕之后,再去加载执行后面的一个.
<script>
var a = 10;
</script>
<script>
console.log(a); // 输出10
</script>
<script>
console.log(a); // ReferenceError: a is not defined
</script>
<script>
var a = 10;
</script>
递归函数(重要、了解)
递归函数指的是函数自己再函数体内部调用自己.
注: 无停止条件的递归 就是死循环 写递归函数,先写停止条件
// a变量一定要定义在函数外部
var a = 0;
function demo() {
a++;
if (a >= 10) {
return;
}
demo();
}
demo(); // 循环让a自加10次 之后就停止
作用域的机制
作用域是变量的生效的范围。
变量操作又分为使用变量
与 赋值变量
- 使用变量
- 出现在表达式中,赋值语句右侧。
- 访问变量规则
- 当访问变量的时候,会先查看当前作用域中是否存在该变量
- 如果有,就使用,并终止查找。
- 如果没有,就将会向上一层级作用域中寻找。
- 依次向上,直到找到,或者到了全局作用域中还没有找到,就会报错。
- 赋值变量
- 只出现在赋值语句左侧
- 赋值变量规则
- 当对一个变量进行赋值的时候,会先查看当前作用域中是否存在该变量
- 如果有,就赋值。
- 如果没有,就向上一层级查找。
- 依次向上,直到找到,或者到了全局作用域中还没有找到
就会在全局作用域中悄悄的声明这个变量并赋值
。
// 当前是全局作用域
var num = 100; // 在全局作用域中定义的变量
// 定义一个函数
function demo() {
var num = 101; // 这是在函数作用域中定义的变量
console.log(num);
}
// 执行函数
demo(); // 101
解释: 当在函数内部访问变量num的时候,先看当前作用域中是否有num 找到了! 于是就用101 输出101
var num = 100; // 在全局作用域中定义的变量
// 定义一个函数
function demo() {
// var num; // 因为声明提升的原因 代码其实是这样子的
console.log(num);
var num = 101; // 这是在函数作用域中定义的变量 虽然定义是在这里 但是提升了
}
// 执行函数
demo(); // undefined
解释: 依旧是作用域的问题,但是因为输出代码在前面,所以有些同学可能会误以为会输出100 但是不要忘记变量的查找规则与预解析!!!
var num = 100; // 在全局作用域中定义的变量
// 定义一个函数
function demo() {
var num = 101;
}
// 执行函数
demo();
// num是多少
console.log(num); // 100
解释: 作用域的问题,因为输出的代码是在全局作用域中的,所以会直接访问全局中的变量 而与函数内部的变量无关
var num = 100; // 在全局作用域中定义的变量
// 定义一个函数
function demo() {
num = 101;
}
console.log(num); // 100
// 执行函数
demo();
// num是多少
console.log(num); // 101