原型的概念还是非常复杂且容易令人产生错误的,本文第一版就有很多错误概念,这里再修改后,就相对少多了 (应该吧,欢迎指出错误)
JS 是一门基于原型的语言,其他语言通过类描述和实例化对象,JS 通过构造函数描述和实例化对象,通过原型实现对象继承。
JS 中几乎每个对象都有隐式原型 __proto__
,相当于他的父对象,但是基本没有显式原型 prototype
(除了函数),这里的对象可以是普通的对象、也可以是函数等,他们都会继承有其他的东西
每个构造函数上都有一个显式原型,用于描述创建的对象的属性和行为,对象的隐式原型等于它构造函数的显式原型
当对象上找不到某个属性时,他就会往原型上寻找,原型上没有就会向原型的原型上寻找,这也就是原型链的基本概念
A
,在 A
中使用 this
描述要创建的对象的属性和方法,prototype
描述在创建的对象上继承的属性和方法,修改 prototype
会影响所有实例化的对象contructor
获取到构造函数的引用,通过 __proto__
获取到原型A
的原型的构造函数实际上是函数 A
本身jsfunction A() {}
const f1 = new A();
// __proto__ 的引用和 prototype 的引用是相等的,但是如果修改了prototype,__proto__ 的引用不会改变
f1.__proto__ === A.prototype; // true
// f本身是没有constructor属性的,它是通过原型链找到的
f1.__proto__.constructor === A; // true
// 如果修改prototype是一个有原型的对象,新的实例化对象的构造函数不指向A
function B() {}
A.prototype = {
constructor: B,
};
const f2 = new A();
f2.__proto__.constructor === A; // false
f2.__proto__.constructor === B; // true
// 因为f1.__proto__ 还是原来那个对象,所以f1的构造函数还是A
f1.__proto__.constructor === A; // true
[Object: null prototype]{}
,而他的隐式原型最终会指向 null
,这也就得到了原型链的终点 null
Object
构造函数的显式原型是 [Object: null prototype]{}
jsconst obj1 = new Object()
obj1.__proto__ // [Object: null prototype] {}
obj1.__proto__ === Object.prototype // true
obj1.__proto__.__proto__ // null
obj1.__proto__.constructor === Object // true
注:在浏览器控制台可以打印对象结构,以下是各个对象的结构
Object
- 实例化对象
obj1
obj1
的隐式原型/Object
的显式原型
函数的构造函数和实例化函数之间的关系也比较特殊
Function
的显式原型和隐式原型是同一个函数,这个函数的 constructor
指向 Function
f
默认自带一个显式原型,这和普通的实例化对象不一样,同时这个显式原型自带一个 constructor
指向 f
f
的隐式原型等于 Function
的原型注:在浏览器控制台可以打印对象结构,以下是各个对象的结构
Function
- 实例化函数
f
Function
的原型函数f
的显式原型prototype
除了函数本身的原型关系,它的原型和对象也有一定的原型关系
jsFunction.prototype // f () { [native code] }
Function.__proto__ === Function.prototype // true
Function.__proto__.constructor === Function // true
Function.__proto__.__proto__ // [Object: null prototype] {}
Object.__proto__ // f () { [native code] }
Object.__proto__ === Function.prototype // true
Object.__proto__.constructor === Function // true
根据上面的分析,就可以得出原型的全貌图了,直接看的话还是太抽象了,可以拆开分析,使用代码验证。
本文作者:pepedd864
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!