前端知识点---原型-原型链(javascript)

news/2025/3/17 11:57:10/

文章目录

  • 原型
  • 原型链:
  • 实际应用
  • 面试题回答

原型

原型:每个函数都有prototype属性 称之为原型

因为这个属性的值是个对象,也称为原型对象

只有函数才有prototype属性

作用:
1.存放一些属性和方法
2.在Javascript中实现继承

const arr = new Array(1, 2, 3, 4)
console.log(arr.reverse)

为什么创建好了就可以使用这些方法呢? 就是原型的存在

Array构造函数也是一个函数 , 只要是函数就有个原型 就是Array.prototype

打开mdn
在这里插入图片描述
在这个原型身上已经挂载了很多方法, 这些方法是可以给所有的数组实例去使用的

为什么实例可以去使用这些方法呢 , 是因为_porto_

每个对象都有_proto_属性

作用: 这个属性指向它的原型对象
在这里插入图片描述

原型链:

在这里插入图片描述

关系总结:

构造函数 -> prototype -> 构造函数的原型对象
构造函数的原型对象 -> proto -> Object.prototype
Object.prototype -> proto -> null(原型链的终点)
代码演示:

function Person(name, age) {this.name = name;this.age = age;
}const p = new Person("张三", 25);// p 的 __proto__ 指向 Person.prototype
console.log(p.__proto__ === Person.prototype); // true// Person.prototype 的 __proto__ 指向 Object.prototype
console.log(Person.prototype.__proto__ === Object.prototype); // true// Object.prototype 是原型链的终点
console.log(Object.prototype.__proto__); // null

解释:
Person.prototype.proto 确实指向 Object.prototype。
Object.prototype 没有更上层的原型,所以它的 proto 是 null。

所以,构造函数的原型对象最终的 proto 是指向 Object.prototype,而 Object.prototype 的 proto 是 null,这是原型链的终点。

实际应用

  1. 共享方法,减少内存开销
    在大型项目中,如果每个实例都独立创建相同的方法,会占用大量内存。原型可以让多个实例共享方法,从而提高性能。

示例:创建对象的优化

function User(name) {this.name = name;
}// 将方法放在 prototype 上,所有实例共享
User.prototype.sayHello = function() {console.log("Hello, my name is " + this.name);
};let user1 = new User("Alice");
let user2 = new User("Bob");user1.sayHello(); // 输出: Hello, my name is Alice
user2.sayHello(); // 输出: Hello, my name is Bob

✅ 优点:所有 User 实例共享 sayHello 方法,而不是每次创建实例都生成新的方法,节省内存。

  1. 继承与扩展
    在项目中,多个对象可能有相似的行为,我们可以利用原型继承来减少代码重复,提高复用性。

示例:父类与子类继承

function Animal(name) {this.name = name;
}// 父类原型方法
Animal.prototype.speak = function() {console.log(this.name + " makes a sound");
};// 子类
function Dog(name, breed) {Animal.call(this, name); // 继承属性this.breed = breed;
}// 继承父类的方法
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;// 添加子类特有方法
Dog.prototype.bark = function() {console.log(this.name + " barks!");
};let dog1 = new Dog("Buddy", "Labrador");
dog1.speak(); // 输出: Buddy makes a sound
dog1.bark();  // 输出: Buddy barks!

✅ 优点:

Dog 继承了 Animal 的 speak 方法,无需重复定义。
Dog.prototype 还能额外扩展 bark 方法,增强灵活性。
3. 扩展原生对象
有时候我们需要扩展 JavaScript 自带的对象,比如 Array、String 等。

示例:扩展 Array.prototype

Array.prototype.sum = function() {return this.reduce((total, num) => total + num, 0);
};let numbers = [1, 2, 3, 4, 5];
console.log(numbers.sum()); // 输出: 15

✅ 优点:给所有数组对象增加 sum 方法,方便项目中复用。

⚠️ 注意:扩展原生对象可能会影响第三方库,应谨慎使用!

  1. 实现类的私有属性
    在 ES5 时代,我们可以通过原型和闭包结合,模拟私有变量,防止外部直接访问。

示例:使用闭包模拟私有属性

function Person(name) {let _age = 25; // 私有变量,外部无法直接访问this.name = name;this.getAge = function() {return _age;};
}let p1 = new Person("Alice");
console.log(p1.name);  // Alice
console.log(p1.getAge()); // 25
console.log(p1._age);  // undefined,无法直接访问

✅ 优点:保护 _age 变量不被外部随意修改,提高安全性。

  1. 结合原型模式和单例模式
    在实际开发中,我们可能希望某个对象只存在一个实例(比如配置管理、数据库连接池等)。可以结合原型模式和单例模式来实现。

示例:全局配置管理

const Config = (function() {function Config() {this.theme = "dark";this.language = "en";}let instance;Config.getInstance = function() {if (!instance) {instance = new Config();}return instance;};return Config;
})();let config1 = Config.getInstance();
let config2 = Config.getInstance();console.log(config1 === config2); // true,说明是同一个实例

✅ 优点:

只创建一个 Config 实例,避免重复初始化配置,提高效率。
总结

应用场景代码示例主要作用
方法共享User.prototype.sayHello让多个实例共享方法,节省内存
继承与扩展Dog.prototype = Object.create(Animal.prototype)复用父类方法,减少代码重复
扩展原生对象Array.prototype.sum添加全局通用方法,增强功能
私有属性let _age = 25;保护数据,防止外部修改
单例模式Config.getInstance()确保对象全局唯一

在实际项目中,合理运用原型能有效提高代码复用性、减少冗余,并优化性能! 🚀

面试题回答

  • 1.原型:函数都有prototype属性,称之为原型,也称为原型对象N原型可以放一些属性和方法,共享给实例对象使用
    原型可以做继承
  • 2.原型链:对象都有_proto 属性,这个属性指向它的原型对象,原型对象也是对象,也有_proto 属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链,最顶层找不到则返回 null

http://www.ppmy.cn/news/1579801.html

相关文章

利用pprof对golang进行性能分析

利用pprof进行性能分析 pprof性能分析的5个方面 一、性能分析的五个核心维度 CPU分析 - 剖析程序的CPU使用情况,定位高耗时函数 内存分析 - 追踪内存分配与泄露,优化内存使用模式 IO分析 - 监控文件/网络IO操作,发现瓶颈资源 Goroutine分…

程序地址空间:深度解析其结构,原理与在计算机系统中的应用价值

目录 1. 程序地址空间回顾 1.1 虚拟地址 2.进程地址空间 分页&虚拟地址空间 引入新概念 解释上述关于同样的地址不同的变量值问题 回答一个历史遗留问题 ​编辑 3.虚拟内存管理 虚拟内存是什么 虚拟地址空间区域划分 为什么要有虚拟地址空间 1. 程序地址空间回…

C++:二分习题

1. 借教室 503. 借教室 - AcWing题库 在大学期间,经常需要租借教室。 大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。 教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。  面对海…

ICMP 协议

文章目录 ICMP 协议概述数据包格式实例分析ICMP 请求ICMP 应答 参考 本文为笔者学习以太网对网上资料归纳整理所做的笔记,文末均附有参考链接,如侵权,请联系删除。 ICMP 协议 概述 ICMP(Internet Control Message Protocol&…

机器学习中的激活函数是什么起什么作用

在机器学习,尤其是神经网络中,​激活函数​(Activation Function)是一个非常重要的组件。它的主要作用是为神经网络引入非线性,从而使神经网络能够学习和表示复杂的模式或函数。 1.激活函数的定义 激活函数是一个数学…

Matlab 汽车振动多自由度非线性悬挂系统和参数研究

1、内容简介 略 Matlab 169-汽车振动多自由度非线性悬挂系统和参数研究 可以交流、咨询、答疑 2、内容说明 略 第二章 汽车模型建立 2.1 汽车悬架系统概述 2.1.1 悬架系统的结构和功能 2.1.2 悬架分类 2.2 四分之一车辆模型 对于车辆动力学,一般都是研究其悬…

90.HarmonyOS NEXT应用发布与版本管理指南:规范化发布流程

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT应用发布与版本管理指南:规范化发布流程 文章目录 HarmonyOS NEXT应用发布与版本管理指南:规范化发布流程1.…

Linux基础开发工具—vim

目录 1、vim的概念 2、vim的常见模式 2.1 演示切换vim模式 3、vim命令模式常用操作 3.1 移动光标 3.2 删除文字 3.3 复制 3.4 替换 4、vim底行模式常用命令 4.1 查找字符 5、vim的配置文件 1、vim的概念 Vim全称是Vi IMproved,即说明它是Vi编辑器的增强…