javascript原型链如何工作_怎样理解原型继承与类语法糖【教程】

发布时间 - 2026-01-30 00:00:00    点击率:
原型链查找属性时,先查对象自身,再沿__proto__逐级向上,直到Object.prototype.__proto__ === null为止;写属性默认只改自身,不污染原型。

原型链怎么查找属性?一句话说清机制

当你写 obj.method(),JS 先查 obj 自身有没有 method;没有就顺着 obj.__proto__ 找,再没就继续找 obj.__proto__.__proto__,直到碰到 Object.prototype.__proto__ === null 停止。这个“一级一级往上翻家谱”的过程就是原型链查找。

  • 所有普通对象的终点都是 Object.prototype,所以都能用 toString()hasOwnProperty()
  • 数组、函数、日期等内置类型也走这条路:比如 [].push 是从 Array.prototypeObject.prototypenull
  • 写属性(如 obj.x = 1)默认只改自身,不会污染原型——这是避免意外共享的关键设计

为什么 Child.prototype = Parent.prototype 是危险操作?

这会让子类和父类共用同一份原型对象,改一个就等于改两个。比如你给 Child.prototype.sayHi 赋值,Parent 实例也会突然多出这个方法——这不是继承,是“原型污染”。

  • 正确做法是用 Object.create(Parent.prototype),它新建一个空对象,并把它的 __proto__ 指向 Parent.prototype
  • ES6 的 class A extends B 底层干的就是这事:A.prototype.__proto__ 被设为 B.prototype,同时保留 A.prototype.constructor 指向 A
  • 漏掉 constructor 重置会导致 instanceof 或序列化时出问题,例如 new A() instanceof A 可能返回 false

new Foo() 到底发生了什么?三步拆解

不是语法魔法,是明确的三步执行:

  • 创建一个空对象,内部 [[Prototype]] 指向 Foo.prototype(即 obj.__proto__ === Foo.prototype
  • 以该对象为 this 执行 Foo.call(obj, ...args),把实例属性挂到对象上
  • 如果构造函数显式返回一个对象,则返回它;否则返回刚创建的对象

这意味着:构造函数里定义的属性(如 this.name)属于每个实例;而挂在 Foo.prototype 上的方法(如 Foo.prototype.say)被所有实例共享——这才是内存友好的关键。

类语法糖(class)掩盖了哪些原型细节?

class 看起来像 Java,但底层完全依赖原型链。比如这段代码:

class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise'); } }
class Dog extends Animal { constructor(name, breed) { super(name); this.breed = breed; } speak() { consol

e.log(this.name + ' barks'); } }

它等价于手动设置原型链 + 调用 super(),而 super() 本质就是确保子类构造函数里能正确访问父类的 this 和原型方法。但要注意:

  • extends null 是合法的,此时 Dog.prototype.__proto__null,不再继承 Object.prototype 的方法(toString 就会报错)
  • 静态方法(static method)其实是挂在构造函数本身上的,即 Dog.method()Dog.__proto__.method(),和实例原型链无关
  • 箭头函数不绑定 this,在类方法中用箭头函数定义回调时,this 会指向定义时的实例,而不是调用时的上下文——这点和原型链无关,但常被误认为是“继承问题”

真正容易被忽略的,是原型链的动态性:你在运行时改 Animal.prototype.speak,所有已存在的 Dog 实例也会立刻生效——这不是 bug,是设计,但也是调试时最让人抓狂的点之一。


# javascript  # es6  # java  # js  # 为什么  # speak  # Static  # Array  # Object  # NULL  # 父类  # 子类  # 构造函数  # 继承  # class 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何用免费手机建站系统零基础打造专业网站?  如何快速上传自定义模板至建站之星?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?  Laravel怎么上传文件_Laravel图片上传及存储配置  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  用yum安装MySQLdb模块的步骤方法  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  油猴 教程,油猴搜脚本为什么会网页无法显示?  Laravel怎么导出Excel文件_Laravel Excel插件使用教程  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  宙斯浏览器怎么屏蔽图片浏览 节省手机流量使用设置方法  如何用景安虚拟主机手机版绑定域名建站?  Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权  ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】  香港服务器网站卡顿?如何解决网络延迟与负载问题?  Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案  JS经典正则表达式笔试题汇总  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  Laravel定时任务怎么设置_Laravel Crontab调度器配置  Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】  高防服务器如何保障网站安全无虞?  lovemo网页版地址 lovemo官网手机登录  Laravel如何处理和验证JSON类型的数据库字段  如何在不使用负向后查找的情况下匹配特定条件前的换行符  Laravel如何使用Vite进行前端资源打包?(配置示例)  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  如何在万网利用已有域名快速建站?  Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能  Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】  如何注册花生壳免费域名并搭建个人网站?  独立制作一个网站多少钱,建立网站需要花多少钱?  制作公司内部网站有哪些,内网如何建网站?  Laravel如何使用Livewire构建动态组件?(入门代码)  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  中山网站推广排名,中山信息港登录入口?  Android自定义listview布局实现上拉加载下拉刷新功能  Laravel如何升级到最新版本?(升级指南和步骤)  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  如何在宝塔面板创建新站点?  JS中对数组元素进行增删改移的方法总结  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  如何确保FTP站点访问权限与数据传输安全?  南京网站制作费用,南京远驱官方网站?  免费视频制作网站,更新又快又好的免费电影网站?  Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程  Laravel Session怎么存储_Laravel Session驱动配置详解  香港服务器如何优化才能显著提升网站加载速度?