JavaScript原型链

先从一个最简单的对象说起。在JS里创建一个对象,通常会用字面量方式:

这个obj看起来很简单,只有一个name属性。但如果我们在控制台输出obj,会发现它其实还有很多其他方法,比如hasOwnProperty、toString等等。这些方法从哪里来的?答案就是原型链。

每个JS对象都有一个隐藏的属性(现在更推荐用Object.getPrototypeOf()方法),它指向该对象的原型。当我们访问一个对象的属性时,如果对象本身没有这个属性,JS引擎就会沿着指向的原型对象去找,如果还找不到,就继续往上一级原型找,直到找到或者到达原型链的顶端null为止。

举个例子,刚才创建的obj对象,它的指向Object.prototype。当我们调用obj.toString()时,obj本身没有toString方法,于是JS引擎就去Object.prototype上找,果然找到了,于是就调用了它。

再来看看函数。每个函数都有一个prototype属性,这个属性是一个对象,我们称之为原型对象。当我们用new操作符调用函数时,创建的对象会自动将这个函数的prototype作为自己的原型。

这里有个很有意思的现象:p1和p2都有自己的name属性,但它们共享同一个sayHello方法。这个sayHello方法就存在于Person.prototype上。通过这种方式,我们可以实现方法的共享,避免每个实例都创建一份方法的拷贝,节省内存。

原型链的真正威力体现在继承上。假设我们有一个Animal类和一个Dog类,Dog要继承Animal:

这里的关键是,它创建了一个以Animal.prototype为原型的新对象,然后赋值给Dog.prototype。这样就建立了原型链:myDog -> Dog.prototype -> Animal.prototype -> Object.prototype -> null。

当我们调用myDog.breathe()时,查找过程是这样的:先在myDog自身找,没有;然后去Dog.prototype找,也没有;再去Animal.prototype找,找到了,于是执行。

在实际开发中,有几个点需要特别注意:

使用可以判断属性是对象自身的还是从原型链继承的。

循环会遍历对象自身和原型链上的所有可枚举属性,如果只想遍历自身属性,需要配合hasOwnProperty使用。

直接给对象赋值不会影响原型链,但修改原型对象会影响所有继承自该原型的实例。

这个例子说明,通过一个对象的修改原型,会影响所有共享该原型的对象。

理解原型链对写出高质量的JS代码很重要。它不仅是实现继承的机制,更是理解JS对象系统的关键。下次当你看到一个对象突然有了你不知道的方法时,别忘了顺着原型链往上找找,说不定会有意外的发现。

相关推荐
龙侠九重天4 分钟前
C# 构建 AI Agent 系统 — 我的实践笔记
开发语言·人工智能·语言模型·自然语言处理·大模型·agent·智能体
SilentSamsara4 分钟前
Pandas 工程化:多层索引、分组聚合与窗口函数的进阶用法
开发语言·python·青少年编程·pandas
协享科技5 分钟前
前端 SSE 流式响应处理实践:从接收、解析到渲染
前端·人工智能·程序人生·go·ai编程·sse
何以解忧,唯有..5 分钟前
Python 字符串完全指南:从基础到高级操作
开发语言·python
kiss strong7 分钟前
自制请求工具
开发语言·python·lua
scan7249 分钟前
短期记忆记忆存储在内存里,一个会话里的多轮对话
开发语言·c#
超人不会飞_Jay12 分钟前
6.2前端笔记
前端·javascript·笔记
鹏大师运维14 分钟前
统信UOS安装Subtitle Edit并使用Edge-TTS生成AI语音教程
linux·前端·人工智能·edge·麒麟·统信uos·ai语音
程序员小羊!20 分钟前
02CSS预备知识
前端·css3
用户0595401744627 分钟前
用LangChain+Chroma实现RAG多轮对话记忆与自动化测试,把bug发现时间从2小时压缩到5分钟
前端·css