当前位置: 首页 > news >正文

JavaScript中的显式原型与隐式原型:深入理解原型链

目录

一、核心概念解析

二、原型链运作机制

三、构造函数的原型三角关系 

四、ES6类语法糖的本质 

五、实现原型继承的三种方式

六、关键注意事项

七、原型链应用场景

八、总结核心要点


一、核心概念解析

  1. 显式原型 (prototype)

    • 函数特有的属性

    • 当函数作为构造函数使用时,其实例会继承该函数的prototype

    • 本质是一个包含constructor属性和共享方法的普通对象

      function Person(name) {this.name = name;
      }// 向显式原型添加方法
      Person.prototype.sayHello = function() {console.log(`Hello, I'm ${this.name}`);
      };// 验证类型
      console.log(typeof Person.prototype); // "object"
      console.log(Person.prototype.constructor === Person); // true

       

  2. 隐式原型 (proto)

    • 每个对象都拥有的属性

    • 指向创建该对象时使用的构造函数的prototype

    • 形成原型链的关键连接点(ES6后建议使用Object.getPrototypeOf()获取)

      const john = new Person("John");// 对象通过__proto__访问构造函数的原型
      console.log(john.__proto__ === Person.prototype); // true// 推荐的标准获取方式
      console.log(Object.getPrototypeOf(john) === Person.prototype); // true

二、原型链运作机制

[实例对象] john│├── __proto__ → [Person.prototype]│        ││        ├── sayHello() │        ││        └── __proto__ → [Object.prototype]│                 ││                 ├── toString()│                 ├── valueOf()│                 ││                 └── __proto__ → null│└── name: "John"

 

原型链查找规则

  1. 访问对象属性时,先在自身查找

  2. 找不到则通过__proto__向上级原型查找

  3. 直到Object.prototype(所有对象的基类)

  4. 最终到达null停止查找

    console.log(john.toString()); // 来自Object.prototype
    console.log(john.sayHello()); // 来自Person.prototype// 验证原型链关系
    console.log(john instanceof Person); // true
    console.log(john instanceof Object); // true

三、构造函数的原型三角关系 

function Animal(type) {this.type = type;
}const dog = new Animal("哺乳动物");// 经典三角关系:
console.log(dog.__proto__ === Animal.prototype); // true
console.log(Animal.prototype.constructor === Animal); // true
console.log(Object.getPrototypeOf(Animal) === Function.prototype); // true

四、ES6类语法糖的本质 

class Vehicle {constructor(wheels) {this.wheels = wheels;}drive() {console.log(`Driving with ${this.wheels} wheels`);}
}// 类本质仍是构造函数
console.log(typeof Vehicle); // "function"const car = new Vehicle(4);// 验证原型关系
console.log(car.__proto__ === Vehicle.prototype); // true
console.log(Vehicle.prototype.__proto__ === Object.prototype); // true

五、实现原型继承的三种方式

  1. 组合继承(最经典方式):

    function Parent(name) {this.name = name;
    }Parent.prototype.speak = function() {console.log(`I'm ${this.name}`);
    };function Child(name, age) {Parent.call(this, name); // 继承属性this.age = age;
    }// 建立原型链
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;// 添加子类方法
    Child.prototype.cry = function() {console.log("Waahh!");
    };

  2. ES6类继承

    class Employee {constructor(name) {this.name = name;}work() {console.log(`${this.name} is working`);}
    }class Manager extends Employee {constructor(name, teamSize) {super(name);this.teamSize = teamSize;}manage() {console.log(`Managing ${this.teamSize} people`);}
    }

  3. Object.create实现纯对象继承: 

    const parent = {greet() {console.log("Hello from parent!");}
    };const child = Object.create(parent, {cry: {value: function() {console.log("Waaaah!");}}
    });

六、关键注意事项

  1. 原型污染风险

    // 修改内置原型需谨慎
    Array.prototype.sum = function() {return this.reduce((a, b) => a + b, 0);
    };const nums = [1, 2, 3];
    console.log(nums.sum()); // 6 - 但可能引发冲突

  2. 性能优化技巧

    // 在构造函数中声明方法(适用于不共享的独特方法)
    function Player(id) {this.id = id;// 每个实例都有独立方法副本this.getID = function() {return this.id;};
    }// 在原型上声明方法(节省内存)
    Player.prototype.getScore = function() {return this.score;
    };

  3. 现代替代方案

  • 使用Object.getPrototypeOf()替代__proto__

  • 使用Object.setPrototypeOf()设置原型

  • ES6的ReflectAPI提供更多元操作

 

七、原型链应用场景

  1. 实现混入模式(Mixins)

    const canEat = {eat() {console.log(`${this.name} is eating`);}
    };const canSleep = {sleep() {console.log(`${this.name} is sleeping`);}
    };function assignPrototypes(target, ...sources) {Object.assign(target.prototype, ...sources);
    }function Cat(name) {this.name = name;
    }assignPrototypes(Cat, canEat, canSleep);const garfield = new Cat("Garfield");
    garfield.eat(); // "Garfield is eating"

八、总结核心要点

  1. 显式原型(prototype):函数的属性,用于实现方法共享

  2. 隐式原型(proto):对象的内部链接,指向其构造函数的prototype

  3. 原型链:通过__proto__连接形成的继承链

  4. 最佳实践

  • 方法定义在prototype上节省内存

  • 属性定义在构造函数中保持独立

  • 避免直接修改内置对象原型

  • 优先使用ES6类语法提高可读性

 

 

 

 

http://www.lqws.cn/news/555823.html

相关文章:

  • 车辆车五项查询API: Python 示例
  • Stewart并联结构两自由度正逆解计算和工作空间仿真
  • Word之电子章制作——1
  • 探索钉钉生态中的宜搭:创建与分享应用的新视界
  • 服务器的维护技术都有哪些?
  • docker+n8n的工作流中无法使用本地ollama服务的问题
  • InnoDB的undo日志涉及的页结构
  • mmap映射物理内存之一cache与lock
  • GeoTools 结合 OpenLayers 实现属性查询
  • Stable Diffusion入门-ControlNet 深入理解 第四课:风格迁移与重绘控制模型——让AI也有“艺术天赋”!
  • Git安装避坑指南
  • 【编程实践】利用python在Blender生成三维模型
  • Kafka 消费者重平衡问题排查与优化实践
  • 在单片机中如何实现一个shell控制台
  • 阿里云-arms监控
  • zookeeper Curator(1):认识zookeeper和操作命令
  • 华为云鸿蒙应用入门级开发者认证 实验部分题目及操作步骤
  • 【龙泽科技】新能源汽车故障诊断仿真教学软件【吉利几何G6】
  • Qt:QCustomPlot库的QCPAxis
  • 第一章 城镇道路工程 1.5 安全质量控制
  • python解释器 与 pip脚本常遇到的问题汇总
  • PYTHON从入门到实践7-获取用户输入与while循环
  • 医疗标准集中标准化存储与人工智能智能更新协同路径研究(上)
  • Next.js实战:AI两小时开发文档社区
  • pytest 中的重试机制
  • 分布式电源采集控制装置:江苏光伏电站的“智能调度中枢
  • 【Java--SQL】${}与#{}区别和危害
  • 如何关闭win更新-随笔11
  • 稳定币独角兽:Circle
  • 零基础langchain实战二:大模型输出格式化成json