深入理解JavaScript原型与原型链

深入理解JavaScript原型与原型链

在JavaScript中,原型(prototype)是一个核心概念,它不仅关乎对象的创建方式,还深刻影响着对象间的继承机制。本文将深入探讨原型的内涵、原型链的工作原理,以及为什么并非所有对象都拥有原型。

原型基础

每个JavaScript函数都自动配备了一个名为prototype的属性,这个属性是一个对象,用来定义当通过该函数作为构造函数创建新对象时,这些新对象(即实例)所共享的属性和方法。简而言之,原型就是构造函数创造实例的蓝图或原型模板。例如:

js 复制代码
function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    console.log("Hello, my name is " + this.name);
};

在这个例子中,Person.prototype.sayHello定义了一个所有Person实例都可以访问的方法。

实例对象与原型的关系

当我们使用构造函数创建一个新对象时,这个新对象会自动链接到构造函数的原型对象上。这种链接是通过每个实例对象内部的特殊属性[[Prototype]](通常可访问的形式为__proto__,尽管不推荐直接使用)实现的。这意味着,实例对象可以访问其构造函数原型上的所有属性和方法,这一过程是隐式的,并且对于开发者来说是只读的。

js 复制代码
Person.prototype.like = '听歌'
function Person() {
    this.name = '田总'
}
let p = new Person()
p.like = '撸铁'

console.log(p.like); // 输出 撸铁

创建了Person的一个实例p,并为其显式地设置了一个同名属性like,值为'撸铁'。由于实例属性优先级高于原型属性,当访问p.like时,它会返回实例自身的like属性值,即'撸铁'

Constructor属性

每个实例对象都有一个constructor属性,它指向创建该实例的构造函数,这对于理解对象的来源非常有用。

js 复制代码
function Car() {
    this.name = 'su7'
}
let car = new Car()
console.log(car.Constructor);// 输出: [Function: Car]

// 实例对象通过constructor来记录我是由谁创建的

在JavaScript中,每个由构造函数创建的对象都会自动获得一个constructor属性,该属性指向创建该对象的构造函数。因此,当你打印car.constructor时,它会显示出Car构造函数本身,这表明car对象是由Car构造函数创建的。

原型链的奥秘

原型链 是JavaScript实现继承的主要机制。当访问一个对象的属性或方法时,如果该对象本身没有定义该属性或方法,JavaScript引擎会继续在其[[Prototype]]指向的对象中寻找,这个过程会一直向上追溯,直到找到该属性或方法,或者到达原型链的末端(null)。这个链式查找的过程确保了对象可以从其祖先那里继承属性和方法。

并非所有对象都有原型?

通常情况下,JavaScript中的每个对象都会有一个原型链,因为就连Object.prototype自身(所有对象原型的最终源头)也有一个null作为其原型,形成了原型链的终点。然而,有一种特殊情况:通过Object.create(null)创建的对象没有原型。这意味着该对象既没有继承自Object.prototype的默认方法(如toString()),也无法通过原型链查找机制获取任何属性或方法。这种对象常用于需要一个"纯净"对象,避免污染全局原型链的场景。

js 复制代码
let a = {
    num: 1
}

let b = Object.create(null);

这段代码在v8引擎中运行,对象a有原型,对象b由于通过Object.create(null)创建,所以该对象没有原型。

结论

原型和原型链是JavaScript实现面向对象编程和继承的核心机制。它们提供了一种灵活且高效的方式来管理对象的属性与方法,同时也允许我们通过构造函数和原型链来模拟经典的类继承模式。理解原型链的运作原理,特别是认识到并非所有对象都默认拥有原型这一特例,对于深入掌握JavaScript语言的精髓至关重要。在实际开发中,合理运用原型链,可以编写出结构清晰、易于维护的代码。

相关推荐
程序边界42 分钟前
lac_agent自愈链路上篇——crontab守护的那些坑与健康检查实战
后端
笨鸟飞不快1 小时前
从 MVC 到 DDD:一次真实的渐进式迁移实录
后端·架构
程序员威哥1 小时前
C#也能玩转YOLO:工业视觉原生推理方案,零Python依赖
后端
kfaino1 小时前
你好,我叫 Prompt——其实,你一直在给 AI 写程序
后端·openai·ai编程
weedsfly1 小时前
还在用 Axios?你可能需要重新理解 XHR 与 Fetch
前端·javascript·面试
CoderWeen1 小时前
从零实现一个 Vue3 流程图编辑器:节点拖拽、贝塞尔连线与框选
前端·javascript
caibixyy1 小时前
springboot+langchain4j实战Day 16 — 混合检索 + Reranker 重排序
后端
Ai拆代码的曹操1 小时前
揭秘"幽灵 CPU":top 抓不到的短命进程,才是真正的 CPU 杀手
后端
IT_陈寒2 小时前
Python里这个赋值坑,连老司机都能翻车
前端·人工智能·后端
唐青枫2 小时前
推荐一个 Zig Web 工程骨架:wing-app
后端