【 预解析、作用域、变量访问规则、递归函数、函数和事件结合使用】

预解析(重点)

  • 预解析 其实就是聊聊 js 代码的编译和执行
  • js 是一个解释型语言,就是在代码执行之前,先对代码进行通读(先找到声明类型的例如:var、funcation)和解释,然后在执行代码
  • 也就是说,我们的 js 代码在运行的时候,会经历两个环节 解释代码 和 执行代码

解释代码

因为是在所有代码执行之前进行解释,所以叫做 预解析(预解释)

需要解释的内容有两个

声明式函数

在内存中先声明有一个变量名是函数名,并且这个名字代表的内容是一个函数

var
  • 关键字
  • 在内存中先声明有一个变量名
  • 看下面一段代码
<script>
fn()
console.log(num)
function fn() {
      
      
console.log('我是 fn 函数')
}
var num = 100
</script>
  • 经过预解析之后可以变形为
<script>
function fn() {
      
      
console.log('我是 fn 函数')
}
var num//变量提升只提升声明部分,只提升到当前作用域的最顶端,赋值还是在下边
fn()
console.log(num)
num = 100
    //函数提升优先于变量提升,变量提升只提升声明部分
</script>
  • 赋值式函数会按照 var 关键字的规则进行预解析

作用域(重点)

  • 什么是作用域,就是一段代码可以生效的范围
  • 这段代码不是在所有地方都可以使用的,而这个变量的使用范围就是作用域

全局作用域

位置:定义变量定义在script标签内,函数外部的区域,具有全局作用域,可以在任何地方使用

生命周期:打开一个页面就像形成了一个全局作用域,页面关闭 全局作用域就销毁了;在函数内部没有声明,但是赋值的,可以理解成全局变量

注意:全局作用域中有一个window的对象,可以直接访问;

  • 全局作用域是最大的作用域

  • 在全局作用域中定义的变量可以在任何地方使用

  • 页面打开的时候,浏览器会自动给我们生成一个全局作用域 window

  • 这个作用域会一直存在,直到页面关闭就销毁了

    // 下面两个变量都是存在在全局作用域下面的,都是可以在任意地方使用的
    var num = 100
    var num2 = 200
    
    

局部作用域

位置:定义在函数内部,变量只能在函数内部访问,外部访问不到

生命周期:函数调用时产生,函数调用结束销毁

​ 调用一次函数就会产生一个局部作用域,多个局部作用域之间是相互独立的

注意:定义在函数内部的变量具有局部作用域,在if 或for 中没有局部作用域

  • 局部作用域就是在全局作用域下面有开辟出来的一个相对小一些的作用域

  • 在局部作用域中定义的变量只能在这个局部作用域内部使用

  • 在 JS 中只有函数能生成一个局部作用域,别的都不行

  • 每一个函数,都是一个局部作用域

    // 这个 num 是一个全局作用域下的变量 在任何地方都可以使用
    var num = 100
    
    function fn() {
      // 下面这个变量就是一个 fn 局部作用域内部的变量
      // 只能在 fn 函数内部使用
      var num2 = 200
    }
    
    fn()
    
    

变量访问规则(重点)

  • 有了作用域以后,变量就有了使用范围,也就有了使用规则
  • 变量使用规则分为两种,访问规则赋值规则

访问规则

  • 当我想获取一个变量的值的时候,我们管这个行为叫做 访问

  • 获取变量的规则:就近原则

    • 首先,在自己的作用域内部查找,如果有,就直接拿来使用
    • 如果没有,就去上一级作用域查找,如果有,就拿来使用
    • 如果没有,就继续去上一级作用域查找,依次类推
    • 如果一直到全局作用域都没有这个变量,那么就会直接报错(该变量 is not defined)
    var num = 100
    
    function fn() {
      var num2 = 200
      
      function fun() {
        var num3 = 300
        
        console.log(num3) // 自己作用域内有,拿过来用
        console.log(num2) // 自己作用域内没有,就去上一级,就是 fn 的作用域里面找,发现有,拿过来用
        console.log(num) // 自己这没有,去上一级 fn 那里也没有,再上一级到全局作用域,发现有,直接用
        console.log(a) // 自己没有,一级一级找上去到全局都没有,就会报错
      }
      
      fun()
    }
    
    fn()
    
    
  • 变量的访问规则 也叫做 作用域的查找机制

  • 作用域的查找机制只能是向上找,不能向下找

    function fn() {
      var num = 100
    }
    fn()
    
    console.log(num) // 发现自己作用域没有,自己就是全局作用域,没有再上一级了,直接报错
    
    

赋值规则

  • 当你想给一个变量赋值的时候,那么就先要找到这个变量,在给他赋值

  • 变量赋值规则:就近原则

    • 先在自己作用域内部查找,有就直接赋值
    • 没有就去上一级作用域内部查找,有就直接赋值
    • 在没有再去上一级作用域查找,有就直接赋值
    • 如果一直找到全局作用域都没有,那么就把这个变量定义为全局变量,在给他赋值
    function fn() {
      num = 100
    }
    fn()
    
    // fn 调用以后,要给 num 赋值
    // 查看自己的作用域内部没有 num 变量
    // 就会向上一级查找
    // 上一级就是全局作用域,发现依旧没有
    // 那么就会把 num 定义为全局的变量,并为其赋值
    // 所以 fn() 以后,全局就有了一个变量叫做 num 并且值是 100
    console.log(num) // 100
    
    

递归函数

  • 什么是递归函数

  • 在编程世界里面,递归就是一个自己调用自己的手段

  • 递归函数: 在函数内部直接或间接的调用函数本身

  • 递归需要有出口,没有出口就形成死递归(Maximum call stack size exceeded:栈溢出\内存溢出)

    // 下面这个代码就是一个最简单的递归函数
    // 在函数内部调用了自己,函数一执行,就调用自己一次,在调用再执行,循环往复,没有止尽
    function fn() {
      fn()
    }
    fn()
    
    
  • 其实递归函数和循环很类似

  • 需要有初始化,自增,执行代码,条件判断的,不然就是一个没有尽头的递归函数,我们叫做 死递归

简单实现一个递归

  • 我们先在用递归函数简单实现一个效果

  • 需求: 求 1 至 5 的和

    • 先算 1 + 2 得 3
    • 再算 3 + 3 得 6
    • 再算 6 + 4 得 10
    • 再算 10 + 5 得 15
    • 结束
  • 开始书写,写递归函数先要写结束条件(为了避免出现 “死递归”)

    function add(n) {
      // 传递进来的是 1
      // 当 n === 5 的时候要结束
      if (n === 5) {
        return 5
      }
    }
    
    add(1)
    
    
  • 再写不满足条件的时候我们的递归处理

    function add(n) {
      // 传递进来的是 1
      // 当 n === 5 的时候要结束
      if (n === 5) {
        return 5
      } else {
        // 不满足条件的时候,就是当前数字 + 比自己大 1 的数字
        return n + add(n + 1)
      }
    }
    add(1)
    
    

函数和事件结合使用

事件:

onclick:点击事件

onmouseover:鼠标移入事件

onmouseout:鼠标移除事件

简单示例:(小小计算器实现案例)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        main {
      
      
            width: 1000px;
            margin: 100px auto;
            text-align: center;
            line-height: 200px;
        }

        input,select,button{
      
      
            display: inline-block;
            border: none;
            width: 50px;
            height: 50px;
            background-color: rgba(127, 255, 212, 0.548);
            text-align: center;
            line-height: 50px;
        }
    </style>
</head>

<body>
    <main>
        <input type="text" id="text1">
        <select id="select">
            <option>+</option>
            <option>-</option>
            <option>*</option>
            <option>/</option>
            <option>%</option>
        </select>
        <input type="text" id="text2">
        <button id="btn">=</button>
        <input type="text" id="text3">
    </main>
</body>

</html>
<script>
    var oText1 = document.getElementById("text1")
    var oText2 = document.getElementById("text2")
    var oText3 = document.getElementById("text3")
    var oselect = document.getElementById("select")
    var oBtn = document.getElementById("btn")
    oBtn.onclick = function () {
      
      
        switch (oselect.value) {
      
      
            case "+":
                oText3.value = Number(oText1.value) + Number(oText2.value);
                break;
            case "-":
                oText3.value = Number(oText1.value) - Number(oText2.value);
                break;
            case "*":
                oText3.value = Number(oText1.value) * Number(oText2.value);
                break;
            case "/":
                oText3.value = Number(oText1.value) / Number(oText2.value);
                break;
            case "%":
                oText3.value = Number(oText1.value) % Number(oText2.value);
                break;
            default:
                break;
        }
    }
</script>

简单了解对象

对象:万事万物皆对象,对象是一系列属性和行为的结合

  • 对象是一个复杂数据类型

  • 其实说是复杂,但是没有很复杂,只不过是存储了一些基本数据类型的一个集合

    var obj = {
      num: 100,
      str: 'hello world',
      boo: true
    }
    
    
  • 这里的 {} 和函数中的 {} 不一样

  • 函数里面的是写代码的,而对象里面是写一些数据的

  • 对象就是一个键值对的集合

  • {} 里面的每一个键都是一个成员

  • 也就是说,我们可以把一些数据放在一个对象里面,那么他们就互不干扰了

  • 其实就是我们准备一个房子,把我们想要的数据放进去,然后把房子的地址给到变量名,当我们需要某一个数据的时候,就可以根据变量名里面存储的地址找到对应的房子,然后去房子里面找到对应的数据

  • show方法是可以用来展示信息的,调用后才能展示出来(对象内的方法)调用时需要"对象.方法"去调用

    <script>
        var obj={
            
            
            //name:"张三",----》键值对,  键值对与键值对之间用,隔开,最后一个不用,
            name:"张三",
            age:14,
            eat(){
            
            
                console.log("火锅")
            },//show方法是可以用来展示信息的,调用后才能展示出来(对象内的方法)调用时需要对象.方法去调用
                show(){
            
             console.log("name"+obj["name"]+"age"+obj["age"])
                }
        }
        console.log(obj);//打印对象
        obj.show();//对象调用方法   .语法
        obj["show"];//对象调用方法   []语法
        //对象访问语法   .语法/[]语法
        var obj = {
            
            }
        //  .  语法
        	obj.name = "张三";
            obj.age = 16; 
         
        //  [ ]语法
        	obj["name"] = "张三";
            obj["age"] = 16;  
        //增:obj.name = "张三"
       // 删:delete obj.name
        //改:
        	obj.name = "李四";
    </script>
    

创建一个对象

  • 字面量的方式创建一个对象

    // 创建一个空对象
    var obj = {}
    
    // 像对象中添加成员
    obj.name = 'Jack'
    obj.age = 18
    
    
  • 内置构造函数的方式创建对象

  • Object 是 js 内置给我们的构造函数,用于创建一个对象使用的

    // 创建一个空对象
    var obj = new Object()
    
    // 向对象中添加成员
    obj.name = 'Rose'
    obj.age = 20
    
    

猜你喜欢

转载自blog.csdn.net/qq_45349018/article/details/121770820