前言
大家好,我是阳阳,小白一枚,这个专栏是我学习原型的全部过程啦,我把看课做的笔记,结合一点百度百科,最终写出了这几篇文章,如果这些对你有帮助,那是再好不过啦~如果哪里还有不足,欢迎评论区指正喔!!
对象原型是JavaScript中实现继承的关键元素,通过隐式原型链,实例对象能够访问构造函数的原型上的属性和方法。了解对象原型的概念及其行为,对于深入理解JavaScript对象之间的关系至关重要。
什么是隐式原型
隐式原型,也称为 __proto__(双下划线 proto)或者[[Prototype]],是 JavaScript 中对象的一个特殊属性。它指向了该对象的构造函数的原型(prototype)。
在 JavaScript 中,每个对象实例都有一个隐式原型。当你创建一个对象实例时,它的隐式原型会指向创建该对象的构造函数的原型。这个关系构成了原型链,允许对象实例继承构造函数原型上的属性和方法。
下面是一个简单的例子:
function Animal(name) {
this.name = name;
}
// 创建一个 Animal 实例
var myAnimal = new Animal('Leo');
// 隐式原型指向构造函数的显示原型
console.log(myAnimal.__proto__ === Animal.prototype); // 输出: true
在这个例子中,myAnimal 实例的隐式原型 __proto__ 指向了 Animal.prototype,建立了实例对象和构造函数原型之间的链接。
再举个栗子:
function Car(){
}
var car = new Car();
console.log(car.constructor);
这里我们创建一个构造函数Car,然后我们创建一个car实例对象,然后打印它的constructor属性,这个属性是用来查找是谁创造了这个对象,实例对象真的有这个属性吗,我们执行一下不就知道了吗?
[Function: Car]
还真有。我们知道,构造函数Car的内部是没有属性和方法的,但是实例对象却能访问到这个constructor属性,那么我们就想,car对象是不是继承到了祖先的属性呢?
于是我们在浏览器控制台里面查找car这个实例对象:
我们发现car是一个Car构造函数创建的对象,再展开发现有个[[Prototype]],它指的是car这个对象的对象原型,又称为对象的隐式原型。
那么这个car对象到底是怎么找到constructor属性的呢?
- 查找对象本身的属性: 首先,JavaScript 引擎会查看
car对象本身是否有constructor属性。如果有,直接返回这个属性值。 - 查找对象的隐式原型: 如果
car对象本身没有constructor属性,JavaScript 引擎会继续沿着原型链,查找car对象的隐式原型(即Car.prototype)。如果在原型链上找到了constructor属性,就返回它。 - 继续向上查找原型链: 如果
Car.prototype上也没有constructor属性,JavaScript 引擎会继续向上查找Car.prototype的隐式原型。这一过程会一直持续,直到找到constructor属性或者到达原型链的末尾(Object.prototype)。 - 返回结果: 如果找到了
constructor属性,返回它的值,否则返回undefined。
所以我们可以总结:
对象原型(隐式原型)
- 实例对象会通过自己的隐式原型去继承构造函数显示原型上的属性和方法
- 当访问对象属性时,先找对象显示具有的属性,没找到再去找对象的隐式原型
- 实例对象的隐式原型 === 构造函数的显示原型
原型链
顺着对象的隐式原型不断地向上查找上一级的隐式原型,直到找到目标或者一直到null,这种查找关系叫做原型链。
如果你能理清这张图片的连接关系,那么你就已经理解了原型链。
- 我们从
f1,f2这两个实例对象出发,他们是构造函数Foo的实例对象,所以他们的隐式原型是Foo函数的显式原型。 Foo.prototype是函数Foo的原型,而Foo.prototype的constructor(创造者)便是函数Foo。- 而
Foo.prototype显式原型也是一个对象,它的隐式原型__proto__是Object函数的显式原型。 - 作为万物之顶的
Object.prototype也是一个对象,但是它的隐式原型__proto__却是null。 - 而
Object.prototype是函数Object的原型,它的constructor也是函数Object。 - 同理
o1,o2是Object的实例对象,他们的隐式原型__proto__就是Object.prototype。 Foo函数名也是一个对象,而它的隐式原型便是Function prototype是函数Function的原型。Function prototype也是对象,它是函数Function的原型,它的constructor是函数Function,同时它的隐式原型__proto__也是Object.prototype。- 而函数名
Function和Object都是对象,他们的隐式原型__proto__都是Function prototype都是函数Function的显式原型。
最后我们来道面试题检验一下:
所有的对象最终都会继承自 Object.prototype ?
Object.prototype 是所有对象原型链的终点。这是因为在 JavaScript 中,对象的原型链是通过每个对象的隐式原型(__proto__ 或 Object.getPrototypeOf())连接起来的。当你创建一个对象时,它的隐式原型指向构造函数的显示原型,这一过程一直持续到原型链的末尾,即 Object.prototype。
但是,也有一些特殊对象例外,它们并不继承自 Object.prototype。例如,null 和 undefined 这两个值并不是对象,它们没有原型链。如果你尝试访问它们的原型链,会得到 null 或 undefined。
最后
至此,隐式原型、原型链已经介绍完毕。希望本文能够帮助你更深入地理解 JavaScript 对象原型链的奥妙,使你在日常的编码工作中能够更加得心应手。
我的Gitee: CodeSpace (gitee.com)
技术小白记录学习过程,有错误或不解的地方还请评论区留言,如果这篇文章对你有所帮助请 “点赞 收藏+关注” ,感谢支持!!