欢迎光临
我们一直在努力

【JavaScript】JS 核心:原型链、继承、闭包、作用域、执行上下文、this 指向、call/apply/bind(附《思维导图》)

文章目录

  • JavaScript 核心知识体系全景总结
    • 一、执行上下文:代码运行的环境基石
      • 1. 三类执行上下文
      • 2. 执行栈(调用栈)
      • 3. 执行上下文的生命周期
        • (1)创建阶段(函数调用后、代码执行前)
        • (2)执行阶段
    • 二、作用域与作用域链:变量访问的静态规则
      • 1. 三类作用域
      • 2. 词法作用域(静态作用域)
      • 3. 作用域链
    • 三、闭包:作用域与生命周期的交叉产物
      • 1. 形成闭包的三个必要条件
      • 2. 闭包的底层本质
      • 3. 典型应用场景
      • 4. 注意事项
    • 四、this 指向:执行上下文的动态主体
      • 1. 六大场景的 this 指向
      • 2. `new` 操作符的执行过程
      • 3. this 绑定优先级(从高到低)
      • 4. 箭头函数的 this 特性
    • 五、call / apply / bind:this 的手动控制
      • 1. 三者核心对比
      • 2. 关键注意点
      • 3. 经典应用场景
    • 六、原型与原型链:对象的属性查找机制
      • 1. 核心概念与三角关系
      • 2. 原型链
      • 3. 标准 API 与误区
    • 七、继承:基于原型链的代码复用方案
      • 1. 七种继承方案演进
        • (1)原型链继承
        • (2)构造函数继承(借调)
        • (3)组合继承
        • (4)原型式继承
        • (5)寄生式继承
        • (6)寄生组合式继承(ES5 最优方案)
        • (7)ES6 Class 继承(语法糖)
    • 八、知识体系整体关联

思维导图

JavaScript 核心知识体系全景总结

以下从运行机制、变量访问、执行主体、对象模型四大维度,系统性梳理原型链、继承、闭包、作用域、执行上下文、this指向、call/apply/bind 七大核心概念,并明确各知识点的内在关联与底层逻辑。


一、执行上下文:代码运行的环境基石

核心定义:JavaScript 引擎执行代码时的运行环境单元,包含代码执行所需的全部信息(变量、函数、作用域链、this 等),是 JS 运行机制的最小单位。

1. 三类执行上下文

  • 全局执行上下文:程序启动时唯一创建,全局代码均在此环境运行。浏览器中对应 window,Node 中对应 globalThis。
  • 函数执行上下文:函数被调用时动态创建,每次调用生成独立的新上下文。
  • Eval 执行上下文:eval() 函数执行时创建,存在安全与性能问题,工程中极少使用。

2. 执行栈(调用栈)

  • 遵循**后进先出(LIFO)**原则,管理所有执行上下文的生命周期。
  • 程序启动时全局上下文入栈;函数调用时函数上下文入栈;函数执行完毕后上下文出栈,控制权回到上一层。

3. 执行上下文的生命周期

分为创建阶段和执行阶段两个步骤:

(1)创建阶段(函数调用后、代码执行前)
  • 变量对象(VO):收集当前上下文中的变量声明、函数声明、形参。函数上下文中的变量对象称为活动对象(AO),进入执行阶段后激活。

    变量提升、函数提升的本质:创建阶段 VO 已完成声明收集,因此代码执行前即可访问声明。

  • 作用域链:由当前 AO 与上层上下文的 VO 组成,负责变量查找。
  • this 绑定:确定当前上下文的 this 指向。
  • (2)执行阶段

    完成变量赋值、函数引用与逐行代码执行;执行完毕后上下文出栈,等待垃圾回收。


    二、作用域与作用域链:变量访问的静态规则

    核心定义:作用域是变量和函数的可访问范围,是一套静态语法规则,在代码定义时就已确定,与执行位置无关。

    1. 三类作用域

    • 全局作用域:最外层作用域,全局变量随处可访问,页面关闭才销毁。
    • 函数作用域:函数内部声明的变量仅在函数内部可访问,外部无法直接读取。
    • 块级作用域(ES6):由 {} 包裹,通过 let/const 声明的变量仅在当前代码块内生效,存在暂时性死区(TDZ),不存在变量提升。

    2. 词法作用域(静态作用域)

    JavaScript 采用词法作用域:函数的作用域在函数定义时就已固化,和调用位置、调用方式无关。与之相对的是动态作用域(如 bash 脚本),作用域在调用时才确定。

    3. 作用域链

    • 定义:访问变量时,JS 引擎从当前作用域开始,逐级向上追溯上层作用域,直到全局作用域,这个链式查找结构就是作用域链。
    • 查找规则:就近原则,内层可访问外层,外层不可访问内层;同名变量内层覆盖外层。
    • 本质:作用域链是执行上下文的核心组成部分,其结构由词法作用域静态决定。

    三、闭包:作用域与生命周期的交叉产物

    核心定义:闭包是函数与其词法作用域的组合。当内部函数引用了外部函数的变量,且内部函数在外部函数执行完毕后依然存活(被返回/被外部持有),就形成了闭包。

    1. 形成闭包的三个必要条件

  • 函数嵌套函数;
  • 内部函数引用外部函数的变量或参数;
  • 内部函数被返回或被外部环境持有(如赋值给全局变量、作为回调函数)。
  • 2. 闭包的底层本质

    外部函数执行完毕后,其执行上下文会出栈,但外部函数的活动对象(AO)不会被垃圾回收——因为内部函数的作用域链仍然持有对它的引用。

    3. 典型应用场景

  • 数据私有化/模块化:模拟私有变量,避免全局污染function createCounter() {
    let count = 0;
    return {
    increment: () => count++,
    getCount: () => count
    };
    }
  • 函数柯里化:参数复用、延迟执行;
  • 防抖与节流:保存上一次执行的状态;
  • 循环变量保留:解决 var 声明下循环变量共享作用域的问题。
  • 4. 注意事项

    • 内存泄漏风险:闭包会长期持有外部作用域引用,若不当使用(如循环引用、持有大对象)会导致内存无法释放;
    • 箭头函数同样可以形成闭包,且其 this 继承自外层词法作用域。

    四、this 指向:执行上下文的动态主体

    核心定义:this 是执行上下文的内置属性,指向当前代码的执行主体。this 的指向在函数调用时动态确定,与函数定义位置无关。

    1. 六大场景的 this 指向

    调用场景this 指向补充说明
    全局环境直接执行 全局对象(浏览器 window / Node globalThis) 严格模式下为 undefined
    普通函数直接调用 全局对象 严格模式下为 undefined
    对象方法调用 调用该方法的对象 谁调用,就指向谁
    构造函数调用(new) 新创建的实例对象 new 会创建空对象并绑定 this
    箭头函数 定义时外层词法作用域的 this 无自身 this,不可被修改
    DOM 事件处理函数 绑定事件的 DOM 元素 addEventListener 回调默认指向元素

    2. new 操作符的执行过程

  • 创建一个全新的空对象;
  • 将空对象的 __proto__ 指向构造函数的 prototype;
  • 将构造函数的 this 绑定到该空对象;
  • 执行构造函数内部代码;
  • 若构造函数返回对象则返回该对象,否则返回这个新对象。
  • 3. this 绑定优先级(从高到低)

    new 绑定 > bind 绑定 > call/apply 绑定 > 对象方法调用 > 默认绑定(普通函数调用)

    4. 箭头函数的 this 特性

    • 没有自身的 this、prototype、arguments,不能作为构造函数;
    • this 继承自定义时外层作用域的 this,且无法通过 call/apply/bind 改变。

    五、call / apply / bind:this 的手动控制

    三者都是 Function.prototype 上的原生方法,核心作用是手动修改函数内部的 this 指向,是 this 动态绑定的核心 API。

    1. 三者核心对比

    方法执行时机参数形式返回值核心特点
    call(thisArg, arg1, arg2, …) 立即执行 参数逐个传递 函数执行结果 改变 this 并立即调用
    apply(thisArg, argsArray) 立即执行 参数以数组/类数组传递 函数执行结果 适合参数数量不确定的场景
    bind(thisArg, arg1, arg2, …) 不立即执行,返回新函数 参数可分批传递(柯里化) 绑定了 this 的新函数 永久绑定 this,支持延迟执行

    2. 关键注意点

    • 若 thisArg 传入 null/undefined,非严格模式下 this 会指向全局对象,严格模式下为传入的值;
    • 箭头函数调用三者无效,无法修改其 this;
    • 多次 bind 只有第一次生效,后续绑定不会覆盖。

    3. 经典应用场景

  • 类数组借用数组方法:Array.prototype.slice.call(arguments);
  • 构造函数继承:子类构造函数中借调父类构造函数;
  • 精准判断数据类型:Object.prototype.toString.call(obj);
  • 固定回调 this:如 React 类组件事件回调绑定。

  • 六、原型与原型链:对象的属性查找机制

    核心定义:原型是 JavaScript 实现面向对象的核心机制,原型链是对象属性/方法的查找规则,也是继承的底层基础。

    1. 核心概念与三角关系

    所有对象与函数都遵循原型三角关联:

  • 构造函数:用于创建对象的函数,自带 prototype 属性;
  • 原型对象:构造函数 prototype 指向的对象,用于存放所有实例共享的属性和方法;
  • 实例对象:通过 new 构造函数创建的对象,自带 __proto__(内部属性 [[Prototype]]),指向构造函数的原型对象;
  • constructor 属性:原型对象的 constructor 指回对应的构造函数。
  • 核心公式:

    实例.__proto__ === 构造函数.prototype
    构造函数.prototype.constructor === 构造函数

    2. 原型链

    • 定义:原型对象本身也是普通对象,同样拥有自己的 __proto__,指向其构造函数的原型;层层向上追溯,直到 Object.prototype.__proto__ === null,这条链式结构就是原型链。
    • 属性查找规则:访问对象属性时,先查找对象自身;找不到则沿 __proto__ 向上遍历原型链;到顶端仍未找到则返回 undefined。
    • 属性遮蔽:对象自身属性与原型属性同名时,优先读取自身属性。

    3. 标准 API 与误区

    • __proto__ 是浏览器实现的非标准属性,工程中推荐使用:
      • Object.getPrototypeOf(obj):获取对象原型
      • Object.setPrototypeOf(obj, proto):设置对象原型
    • 所有函数的默认原型都是 new Object(),因此原型链最终都会指向 Object.prototype。

    七、继承:基于原型链的代码复用方案

    JavaScript 的继承本质是基于原型链的代码复用,经历了多个演进阶段,最终形成成熟的最优方案。

    1. 七种继承方案演进

    (1)原型链继承
    • 实现:Child.prototype = new Parent()
    • 缺陷:父类引用属性被所有子类实例共享;创建子类时无法向父类传参。
    (2)构造函数继承(借调)
    • 实现:子类构造函数内执行 Parent.call(this, …args)
    • 优点:可传参、避免引用共享;
    • 缺陷:只能继承实例属性,无法继承父类原型方法,方法无法复用。
    (3)组合继承
    • 实现:原型链继承方法 + 构造函数继承属性
    • 缺陷:调用两次父类构造函数,子类原型上存在多余的父类实例属性。
    (4)原型式继承
    • 实现:基于已有对象创建新对象,对应 ES6 Object.create()
    • 缺陷:引用属性仍然被所有新对象共享。
    (5)寄生式继承
    • 实现:在原型式基础上封装函数,为对象新增方法
    • 缺陷:方法无法复用,每个对象都有独立副本。
    (6)寄生组合式继承(ES5 最优方案)
    • 核心:子类原型继承父类原型的副本,不重复调用父类构造函数function inherit(Child, Parent) {
      const proto = Object.create(Parent.prototype);
      proto.constructor = Child;
      Child.prototype = proto;
      }
    • 优势:仅调用一次父类构造函数,无冗余属性,完整保留原型链结构。
    (7)ES6 Class 继承(语法糖)
    • 语法:class Child extends Parent { constructor() { super(); } }
    • 本质:底层仍然是寄生组合式继承,super() 对应构造函数借调,extends 对应原型链关联。
    • 特性:class 必须通过 new 调用,无变量提升;静态方法通过 static 声明,继承自父类本身。

    八、知识体系整体关联

  • 底层运行层:执行上下文是代码运行的最小环境单元,执行栈管理生命周期;每个上下文包含变量对象、作用域链、this 三大核心要素。
  • 变量访问层:作用域是静态语法规则,决定作用域链的结构;闭包是作用域与执行上下文生命周期不一致的产物,让函数可以“记住”定义时的环境。
  • 执行主体层:this 是执行上下文的动态属性,由调用方式决定;call/apply/bind 提供了手动控制 this 的能力。
  • 对象模型层:原型链是对象的属性查找机制,是 JS 面向对象的核心;从原型链到 ES6 Class,本质都是基于原型的代码复用。
  • 赞(0)
    未经允许不得转载:171主机测评 » 【JavaScript】JS 核心:原型链、继承、闭包、作用域、执行上下文、this 指向、call/apply/bind(附《思维导图》)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址