JavaScript 中的原型与继承

发布时间:2026/11/9 1:53:08

JavaScript 中的原型与继承 一、从对象说起, 一切皆对象在 JS 中, 几乎所有的东西都是对象, 或者说最终都会指向某个对象. 比如:let arr [1,2,3];console.log(typeof arr);//objectfunctionfoo() {}console.log(typeof foo);//function (但本质上也是对象)简单的对象创建:let person {name:张三,age:25,sayHi:function() {console.log(你好我是 this.name);}};person.sayHi();// 你好, 我是张三但这样有个问题——每次创建新对象都要写一遍所有属性和方法, 太麻烦了! 于是我们有了后面的构造函数. 二、构造函数对象的工厂functionPerson(name, age) {this.name name;this.age age;this.sayHi function() {console.log(你好, 我是 this.name);};}let person1 newPerson(张三,25);let person2 newPerson(李四,30);person1.sayHi();// 你好, 我是张三person2.sayHi();// 你好, 我是李四这里有几个关键点:1. 函数名通常大写开头这是约定俗成的构造函数命名方式2. 使用new关键字调用3. 函数内部使用this来指代新创建的对象当你使用new调用函数时背后发生了这些事:1. 创建一个全新的空对象2. 将这个空对象的__proto__指向构造函数的prototype属性3. 将构造函数中的this绑定到这个新对象4. 执行构造函数中的代码5. 如果构造函数没有显式返回对象则返回这个新对象三、原型登场上面的构造函数方式有个问题——每个实例都会创建自己的方法副本, 浪费内存, 这时候原型(prototype)就派上用场了!什么是原型?每个函数都有一个prototype属性, 它指向一个对象. 当使用这个函数作为构造函数创建实例时, 所有实例都会共享这个原型对象上的属性和方法.改进版的 Person:functionPerson(name, age) {this.name name;this.age age;}// 将方法放在原型上Person.prototype.sayHi function() {console.log(你好我是 this.name);};let person1 newPerson(张三,25);let person2 newPerson(李四,30);console.log(person1.sayHi person2.sayHi);// true - 现在方法是共享的了什么是原型链?当我们访问一个对象的属性时, JavaScript 会:1. 先在对象自身属性中查找2. 如果没找到, 就去对象的__proto__(即构造函数的prototype) 中查找3. 如果还没找到, 就继续往__proto__.__proto__中查找4. 直到找到Object.prototype(最顶层的原型它的__proto__是null)这就是原型链, JavaScript的继承机制.functionPerson() {}Person.prototype.species 人类;let p newPerson();console.log(p.species);//人类 - 从原型上找到的console.log(p.__proto__ Person.prototype);// trueconsole.log(Person.prototype.__proto__ Object.prototype);// trueconsole.log(Object.prototype.__proto__);// null如果对象自身有属性, 就不会去原型上找了:p.species 地球人;console.log(p.species);//地球人 - 自身的属性console.log(Person.prototype.species);//人类 - 原型上的没变delete p.species;console.log(p.species);//人类 - 删除自身属性后又从原型上找到了四、几种继承的方式1)原型链继承:functionParent() {this.parentProp 父类属性;}Parent.prototype.parentMethod function() {console.log(父类方法);};functionChild() {this.childProp 子类属性;}// 关键点: 子类的原型指向父类的实例Child.prototype newParent();let child newChild();console.log(child.childProp);// 子类属性console.log(child.parentProp);// 父类属性-通过原型链找到的child.parentMethod();// 父类方法问题:所有子类实例共享同一个父类实例的属性(如果是引用类型就麻烦了)创建子类实例时无法向父类构造函数传参2)构造函数继承:functionParent(name) {this.name name;this.colors [red,blue];}functionChild(name, age) {Parent.call(this, name);//关键点:在子类构造函数中调用父类构造函数this.age age;}let child1 newChild(张三,25);child1.colors.push(green);let child2 newChild(李四,30);console.log(child2.colors);//[red, blue]-不受child1影响优点:1. 避免了引用类型属性被所有实例共享2. 可以在子类中向父类传参缺点:方法都在构造函数中定义每次创建实例都会创建一遍方法不能继承父类原型上的方法3)组合继承:结合原型链继承和构造函数继承的优点:functionParent(name) {this.name name;this.colors [red,blue];}Parent.prototype.sayName function() {console.log(this.name);};functionChild(name, age) {Parent.call(this, name);//第二次调用Parentthis.age age;}Child.prototype newParent();//第一次调用ParentChild.prototype.constructor Child;//修复constructor指向Child.prototype.sayAge function() {console.log(this.age);};let child1 newChild(张三,25);child1.colors.push(green);child1.sayName();//张三child1.sayAge();//25let child2 newChild(李四,30);console.log(child2.colors);//[red, blue]4)寄生组合继承:functioninheritPrototype(child, parent) {let prototype Object.create(parent.prototype);// 创建父类原型的副本//Object.create 是创建以指定对象为原型的新对象的方法prototype.constructor child;// 修复constructorchild.prototype prototype;// 将副本作为子类的原型}functionParent(name) {this.name name;this.colors [red,blue];}Parent.prototype.sayName function() {console.log(this.name);};functionChild(name, age) {Parent.call(this, name);this.age age;}// 关键: 使用我们封装的inheritPrototype函数inheritPrototype(Child,Parent);Child.prototype.sayAge function() {console.log(this.age);};let child newChild(张三,25);child.sayName();// 张三child.sayAge();// 25优点:1. 只调用一次父类构造函数2. 子类原型上不会有多余的父类属性3. 原型链保持不变五、ES6的classES6 引入了class语法, 让面向对象编程更加直观:classParent {constructor(name) {this.name name;this.colors [red,blue];}sayName() {console.log(this.name);}}classChildextendsParent {constructor(name, age) {super(name);// 必须在使用this之前调用superthis.age age;}sayAge() {console.log(this.age);}}let child newChild(张三,25);child.sayName();// 张三child.sayAge();// 25class本质上仍然是基于原型的语法糖. 上面的代码大致相当于:functionParent(name) {this.name name;this.colors [red,blue];}Parent.prototype.sayName function() {console.log(this.name);};functionChild(name, age) {Parent.call(this, name);this.age age;}Child.prototype Object.create(Parent.prototype);Child.prototype.constructor Child;Child.prototype.sayAge function() {console.log(this.age);};class还提供了静态方法和属性的简洁写法:classMyClass {staticstaticMethod() {console.log(我是静态方法);}static staticProperty 我是静态属性;}MyClass.staticMethod();//我是静态方法console.log(MyClass.staticProperty);//我是静态属性六、其他相关内容instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上.functionmyInstanceof(instance, constructor) {let proto Object.getPrototypeOf(instance);while (proto) {if (proto constructor.prototype) {returntrue;}proto Object.getPrototypeOf(proto);}returnfalse;}console.log([]instanceofArray);// trueconsole.log(myInstanceof([],Array));// true原型可以被修改, 这可能导致安全问题:// 不要这样做Object.prototype.hack function() {console.log(被黑了);};let obj {};obj.hack();// 被黑了
延伸阅读

更多相关文章

2026/11/8 21:28:20

免费解锁Wand游戏修改器高级功能的完整开源解决方案

免费解锁Wand游戏修改器高级功能的完整开源解决方案 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 还在为Wand(原WeMod)的…

2026/11/5 16:20:54

第七史诗智能自动化助手:彻底解放双手的终极游戏伴侣

第七史诗智能自动化助手:彻底解放双手的终极游戏伴侣 【免费下载链接】e7Helper 【Epic Seven Auto Bot】第七史诗多功能覆盖脚本(刷书签🍃,挂讨伐、后记、祭坛✌️,挂JJC等📛,多服务器支持📺&a…

2026/11/4 1:18:29

亚洲EMBA怎么选?2026民企老板择校性价比实测榜单

【客观测评声明】本文为独立财经测评内容,无硬性品牌营销导向,基于2026年亚洲主流EMBA项目公开数据,从民企实业经营视角,客观拆解各项目适配度、优势与短板,为企业创始人、高管提供理性择校参考,规避择校踩…

2026/11/9 1:48:21

高压电工证查询网上查询在哪考 外省证怎么转过来

高压电工证查询网上查询在哪考 外省证怎么转过来 之前考的证在外省能不能转过来?这个问题我见过太多人问了,特别是在济源这样的地方,很多人在外地打工时考的高压电工证,回到本地后不知道怎么操作。别急,今天咱们就来聊清楚【高压电工证查询网上查询】这…

2026/11/9 1:48:21

邢台市哪里办电工证千万别踩坑,怕考不过白交培训费

邢台市哪里办电工证千万别踩坑,怕考不过白交培训费 怕考不过白交培训费?现在考电工证,很多人不是怕考不过,而是怕找错了地方,白花了钱还拿不到证。尤其是邢台市的电工证报考,坑太多,选错机构,不仅浪费时间,还可能影响以后的工作发展。别再踩坑了,今…

2026/11/9 1:48:21

阿克苏地区煤气作业证过期了怎么复审?保姆级教程全在这里

阿克苏地区煤气作业证过期了怎么复审?保姆级教程全在这里 证书过期了不知道怎么复审延期?你不是一个人。很多特种作业人员在拿到【阿克苏地区煤气作业证】后,因为工作繁忙、信息不畅或者对政策不了解,导致证书过期却不知如何处理。别急,这是一份…

2026/11/9 1:48:21

厦门高压电工证科目一怎么考?官方报名入口在这里,别再走弯路

厦门高压电工证科目一怎么考?官方报名入口在这里,别再走弯路 证书过期了不知道怎么复审延期?很多人在拿到高压电工证后,常常忽视证书的复审时间,直到需要使用证书时才发现已经过期。尤其是像厦门高压电工证科目一这样的关键考试,不仅关乎资格,还直接影…

2026/11/9 1:48:21

咸阳电工证查询网千万别踩坑,工地太忙根本没时间复习考试怎么办?

咸阳电工证查询网千万别踩坑,工地太忙根本没时间复习考试怎么办? 工地太忙根本没时间复习考试,特种作业证的考试和复审成了很多建筑从业者的心头病。尤其是电工证,不仅关系到日常作业安全,也直接影响到你的职业发展和薪资水平。别以为只要在咸阳电工证查…

2026/11/9 1:43:20

乐山特种工培训官方回应实操考试心里没底怕挂科怎么破

乐山特种工培训官方回应实操考试心里没底怕挂科怎么破 实操考试心里没底怕挂科?很多人在报名乐山特种工培训时,最大的顾虑不是学费,而是能不能顺利通过考试。尤其是像低压电工、焊工、高处作业这类实操占分比高的工种,很多人担心自己操作不熟练、动作不标…

2026/11/9 0:37:55

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/9 0:03:09

建设厅的特种工有哪些含金量高?别交完钱考不过

建设厅的特种工有哪些含金量高?别交完钱考不过 怕考不过白交培训费?别急,先搞清楚建设厅的特种工有哪些含金量高的证,再决定是不是值得投入时间和金钱。 建设厅的特种工证是建筑行业里最基础、也最实用的证书之一,涉及多个作业类别,每种证的 含金量…

2026/11/9 0:03:09

荆门市电工证报名怎么考才靠谱 全国通用证别交冤枉钱

荆门市电工证报名怎么考才靠谱 全国通用证别交冤枉钱 怕考不过白交培训费?荆门市电工证报名前必须知道这些避坑指南。别看网上一堆培训机构广告,真要报个电工证,很多人被坑得一塌糊涂。特别是那些打着“包过”旗号的,最后不是考试不过,就是证不是全国通…

2026/11/9 0:03:09

高空电工作业过程通过率揭秘:怎么选靠谱机构不被坑

高空电工作业过程通过率揭秘:怎么选靠谱机构不被坑 不知道去哪报名怕被中介坑?你不是一个人。现在特种作业证报名渠道五花八门,从线下培训机构到线上代理,真假难辨。尤其是像高空电工作业这类高风险、高门槛的作业类型,证书含金量和考试通过率直接影响你…

2026/11/7 14:54:47

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/7 14:50:12

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑