js高级进阶

本文深入探讨JavaScript的高级特性,包括作用域链的原理,局部与全局作用域的访问机制,以及闭包的重要应用。接着,介绍了变量的声明与提升、函数动态参数、剩余参数的使用及其高级技巧,同时讲解了展开运算符的运用,最后详细阐述了箭头函数的特点和用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.作用域链

  <script>
    // 什么是作用域链: 变量的查找机制
    // 大白话: 里面的函数能够看见外面的变量 ---外面看不见里面
    // 官方:  变量查找的时候: 从内往外, 就近查找

    // 全局变量a
    let a = 1;  // 全局变量 任何作用域都可以看见
    function fn() {
      // 局部变量 a ---- 在局部作用域里面声明的变量外面无法访问
      let a = 10
      function g() {
        a = 20 // 这个a 是17行 还是 14行的a
        console.log(a);
      }
      g()
    }

    // 问题: a是全局变量还是局部变量, a的值等于多少?
    fn()
  </script>

1. 局部作用域: 函数作用域 + 块级作用域
2. 全局作用域变量访问机制:  在任何局部作用域里面都可以看见
3. 局部作用域变量的访问机制:在局部作用域里面定义的变量外面看不见
4. 作用域链: 什么是作用域链: 变量的查找机制
            具体是什么机制: 从内向外, 就近查找

闭包的作用

<script>
    // 面试会问
    // 什么是闭包: 闭包就是函数, 内层函数 + 访问了外层函数的变量
    // 闭包的作用: 可以让函数外面访问函数内部的变量 (不能直接访问,需要通过函数调用的形式)
    // 闭包的应用: 数据私有化
    // 闭包的问题: 内存泄露 --- 一直保存在内存里面,不被销毁

    function fn() {
      let num = 10 // 只能在函数里面使用,外面看不到---- 数据私有化
      return function g() {
        num++
        console.log(num);
      }
    }

    const res = fn() // res就是一个函数

    res() // 11 通过闭包,我们可以用函数调用的形式,去访问函数内部的变量
    res() // 12
    res() // 13
    // num += 100 直接报错,因为它是私有变量,外面看不见,只能通过函数调用去访问
    // console.log(num); // 我们之前学习的,在函数外面不能访问函数内部的变量,


    // 通过全局变量的方式,实现调用一次函数,让变量值累加
    let count = 10; // 这个变量是全局变量

    function fn2() {
      count++
      console.log(count);
    }
    // 下面两行的打印分别是多少
    fn2() // 第一次函数调用结束以后,全局变量count的值已经变为了 11
    fn2() // // 第二次函数调用的时候,就是11开始
    count += 100
    console.log(count);
  </script>

3.变量的声明和提升

 <script>
    // 整个函数体提升上来
    // function fn() {
    //   console.log('我是一个函数');
    // }
    // 面试题: 变量的声明提升(var): 提升变量的声明,不提升变量的赋值
    // 在工作里面,我们不会写这样的代码, 纯是为了面试官的考点
    // 我们自己写代码, 一定是先声明,再使用
    var str
    console.log(str);

    str = "hello" // 变量的初始化 === 变量的声明 var str  + 变量的赋值 str = "hello"

    // 正式因为这种写法很奇怪,但是js又不报错,所有es6 发明了 let/const去声明变量

    // console.log(count);
    // let count = 100 现在用let const 声明变量使用 不规范的时候,直接报错

    // count = 10;
    // console.log(count);
    // let count;

    // 对于函数来说,使用function声明一个函数,会把声明提升到当前作用域的顶部
    // 自己写代码,不要先使用在定义, 习惯不好,看起来别扭
    // 任何时候,一定是先声明再使用
    fn()

    function fn() {
      console.log('我是一个函数');
    }

4.函数的动态参数

<script>
    // js给我们函数里面 自动添加了一个变量 动态参数 arguments
    // arguments 伪数组,

    function getSum() { // 形式化的参数: 形参
      let sum = 0;
      // 如果一个程序,不报错,也没有正常结果,那么一定是隐藏的语法写错了
      // i < arguments 这个写法是错误的,但是浏览器不报错,所以不好查找,需要慢慢回忆for循环的基本结构
      for(let i = 0; i < arguments.length; i++) {
        sum += arguments[i]
      }

      console.log(sum);
      // return sum
    }

    // 王瑞蕾, 周明亮, 刘刚强
    const res = getSum(1)  // 一个函数如果没有返回值,打印的结果就是undeifned
    console.log(res); //

    // 需求: 给函数传递任意个数参数,然后对他们求和
    getSum(1) // 实参
    getSum(1, 2, 3)
    getSum(1, 2,3,4,5)
  </script>

5.函数的剩余参数

<script>
    // 剩余参数: es6的新语法, 语法就是 ...
    // 动态参数:是伪数组 --- 只有length属性,可以通过索引号访问, 不能使用各种push等方法
    // 剩余参数:真数组 ----- 工作里面一般使用 剩余参数来解决 这种任意参数的问题

    // 如果不使用动态参数,怎么样对这些任意个数的参数求和
    // function getSum(...args){
    //   console.log(args);
    //   console.log(arguments);
    //   // 自己利用 剩余参数,去写一个求和的函数,使用return的写法

    // }

    // getSum(1)
    // getSum(1, 2)
    // getSum(1, 2, 3, 4, 5)

    function getSum(...args) { // 形式化的参数: 形参
      let sum = 0;
      for(let i = 0; i < args.length; i++) {
        sum += arguments[i]
      }

      // return sum
    }

    // 函数一定要有return 才会有返回值, 如果没有return,就是undefined
    const res = getSum(1,2)
    console.log(res); // undefined
    console.log(getSum(1,2)); // undefined
  </script>

6.函数的剩余参数高级应用

 function getNum(x, z, ...y){
      console.log(x,z, y);
    }

    // 我想吧第一个参数单独拿出来,剩下的放到剩余参数里面去
    getNum('我是最厉害的', 'b', 'c', 'd')

7.展开运算符

<script>
    // 函数动态参数,剩余参数(函数里面) --- (展开运算符--数组前面)

    // 展开运算符: 求最大最小值, 合并数组

    const arr = [1,2,3,4,5]
    const arr2  = [6,7,8,9]

    // console.log(arr);
    // console.log(...arr);

    // 求最大值 1,2,3,4,5
  
 
    // console.log(Math.max(1,2,3,4,5));
    console.log(Math.max(...arr));
    console.log(Math.min(...arr));

    // const arr3 = [arr, arr2]
    const arr3 = [...arr, ...arr2]  
    console.log(arr3);

8.箭头函数

<button class="btn">我是按钮</button>
  <script>
    // 谁来调用这个函数,函数内部的this就指向谁
    // 箭头函数里面, 没有this值, 如果我们访问的话,会去上一层作用域里面找this
    // (this就是一个局部变量,系统自动创建,箭头函数里面没有,他就会顺着作用域链往上找,就近原则)

    // 全局环境下面的this值
    console.log(this);

    const obj = {
      name: '小猪佩奇',
      getName() {
        // 函数内部的this值,是函数调用的使用,由系统自动创建的一个变量
        // 谁来调用这个函数,函数内部的this就指向谁
        console.log(this === obj);
      }
    }
    obj.getName()

    // 1. dom事件
    const btnDom = document.querySelector('.btn')
    // 后面的匿名函数, 当用户点击按钮的时候,由按钮去调用这个回调函数,所有函数内部的this就指向btn
    // btnDom.addEventListener('click', function() {
    //   console.log(this);
    // })
    btnDom.addEventListener('click', () => {
      console.log(this); // 为什么是window?1. 箭头函数内部没有this, 2. 去上一层作用域里面找
    })

    // 2. 对象里面的方法调用
    const  obj2 = {
      name: '123',
      getName: function() {
        console.log(this); // 谁调用这个函数,this

        const fn = () => {
          console.log(this); // 没有this, 上一层作用域里面
        }
        fn()
      }
    }
    obj2.getName()

    const  obj3 = {
      name: '123',
      getName: () => {
        console.log(this);

        const fn = () => {
          console.log(this);
        }
        fn()
      }
    }
    obj3.getName()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值