惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Simon Willison's Weblog
Simon Willison's Weblog
P
Privacy International News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
Troy Hunt's Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Attack and Defense Labs
Attack and Defense Labs
S
Secure Thoughts
V2EX - 技术
V2EX - 技术
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
O
OpenAI News
Cloudbric
Cloudbric
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Help Net Security
Help Net Security
Cyberwarzone
Cyberwarzone
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Spread Privacy
Spread Privacy
NISL@THU
NISL@THU
N
News and Events Feed by Topic
T
Tenable Blog
S
Security @ Cisco Blogs
N
News and Events Feed by Topic
The Hacker News
The Hacker News
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google DeepMind News
Google DeepMind News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
P
Proofpoint News Feed
Webroot Blog
Webroot Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 三生石上(FineUI控件)
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Jina AI
Jina AI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
L
LangChain Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东

吃猫的鱼个人博客-个人编程技术

鸿蒙安装 Google Play 应用:microG 方案实践 OpenClaw 不是更聪明的 AI,而是能长期跑起来的 AI - 吃猫的鱼个人博客-个人编程技术 GAIA 测评体系 - 吃猫的鱼个人博客-个人编程技术 MCP(模型上下文协议)是什么 - 吃猫的鱼个人博客-个人编程技术 AI简历开发-自定义指令实现图片懒加载 - 吃猫的鱼个人博客-个人编程技术 AI简历开发-新增功能AI对话,深度润色经历、面试拷打 - 吃猫的鱼个人博客-个人编程技术 AI简历-做了个简历生成的项目 - 吃猫的鱼个人博客-个人编程技术 AI简历项目开发-从产品AI功能构思到封装AI润色组件 - 吃猫的鱼个人博客-个人编程技术 前端进阶-事件循环 - 吃猫的鱼个人博客-个人编程技术 AI简历开发 - 记录如何实现纯前端切换简历多模板 - 吃猫的鱼个人博客-个人编程技术
JS进阶-原型链 - 吃猫的鱼个人博客-个人编程技术
吃猫的鱼 · 2025-02-13 · via 吃猫的鱼个人博客-个人编程技术

吃猫的鱼

原型链的定义

JavaScript 是基于 原型(prototype) 继承的语言,每个对象都可以从它的 原型 继承属性和方法。
原型链(Prototype Chain) 就是多个对象通过 prototype 关联形成的链式结构,用于实现继承。

__proto__(原型指向):实例对象内部的 __proto__ 连接到其构造函数的 prototype,形成原型链。

实例对象.__proto__ === 构造函数.prototype

按照我自己的理解来说,就是 创建对象的那个东西长什么样子。

举个例子:有一批东西产品,是从一个模具做出来的。那这个产品 的__proto__(原型)就是这个模具,这个产品有自己的颜色和功能。(颜色可以看作这个产品自身的属性,每个都不同;功能是共享模具的,每个对象都一样)。

下面用js来深刻体会一下原型链:

// 1 定义一个模具(构造函数)
function Product(color) {
    this.color = color; // 每个产品(实例)都有不同的颜色
}

// 2 给模具添加通用功能(方法)
Product.prototype.use = function() {
    console.log("Using the product!");
};

// 3 生产两个产品(实例)
const productA = new Product("red");
const productB = new Product("blue");

console.log(productA.color);  // "red"  (每个实例的属性不同)
console.log(productB.color);  // "blue"

productA.use();  // "Using the product!" (共享方法)
productB.use();  // "Using the product!"

console.log(productA.__proto__ === Product.prototype);  // true
console.log(productB.__proto__ === Product.prototype);  // true

另外,通过在控制台中输出一下原型,帮助理解

function Product(color) {
    this.color = color; // 每个产品(实例)都有不同的颜色
}
Product.prototype.use = function() {
    console.log("Using the product!");
};
const p1 = new Product("red");
// 控制台输出p1原型
console.log(p1.__prodo__)

image-20250211112914168

__proto__和prototype 是什么关系?怎么区分?

prototype:只存在于函数对象,用于定义实例共享的方法和属性

__proto__:任何对象都有,指向创建该对象的构造函数的 prototype

简单来说,它们关系如下

// 构造函数
function Person(name) {
    this.name = name;
}

     //  通过prototype向构造函数添加方法
Person.prototype.sayHello = function() {
    console.log("Hello, my name is " + this.name);
};

// 实例对象
const p1 = new Person('小红');
p1.sayHello()  // Hello, my name is 小红

//简单来说
实例对象.__proto__ === 构造函数.prototype

结合上面的Person,给出下面的一些关系,供理解

console.log(p1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true

一个关系示意图是这样子的:

p1 (实例对象)
   |
   |  __proto__
   ↓
Person.prototype (原型对象)
   |
   |  __proto__
   ↓
Object.prototype
   |
   |  __proto__
   ↓
null  (原型链终点)

深入思考——方法写在构造函数内部&&使用 prototype

经过上面,我就在想方法写在构造函数内部和使用 prototype添加,有什么区别呢?

第一种写法,把方法写在构造函数内部

function Product(color) {
    this.color = color;

    // 每次创建一个实例,就会重新创建一个新函数
    this.use = function() {
        console.log("Using the product!");
    };
}

const p1 = new Product("red");
const p2 = new Product("blue");

console.log(p1.use === p2.use);  // false (每个实例都有自己的 use 方法,占用更多内存)

第二种写法,使用 prototype 让所有实例共享方法

function Product(color) {
    this.color = color;
}

// use 方法只创建一次,所有实例共享
Product.prototype.use = function() {
    console.log("Using the product!");
};

const p1 = new Product("red");
const p2 = new Product("blue");

console.log(p1.use === p2.use);  // true (所有实例共享同一个 use 方法)

经查,得出结论,写在构造函数内部性能消耗严重

  • 每次 new Product(),都会创建一个新的 use 方法,导致内存浪费
  • 这些 use 方法的功能完全一样,但 JavaScript 仍然要给每个实例分配不同的函数空间。
  • 影响性能,如果创建成百上千个实例,会占用大量内存。

使用 prototype 优势:

  • use 方法只创建一次,所有 Product 实例共享这个方法。
  • 节省内存,不管有多少个实例,它们都复用同一个方法。
  • 提高性能,减少重复创建函数的开销。