1.原型和原型链的定义
原型:JS中除了null之外的JS对象都有一个与之关联的对象,这个对象就是它的原型,并且可以从这个对象继承属性和方法。
tips:上面为什么要强调除了null之外的JS对象?首先
null不是一个JS对象,但是typeof null是等于"object",这是JS的历史遗留问题。我们在谈论JS对象时,经常会特别指出“除了null之外”的对象,以防止混淆。这是因为尽管typeof null返回"object",但在JS中,null实际上代表的是非对象的空值。下面内容中就不强调null了,默认所有JS对象就是除null之外的JS对象
原型链:JS在查找对象属性时,首先会在对象本身上查找,如果没有找到,就会去对象的原型上查找,接下来是原型的原型,依此类推,这样构成的一条链路我们称为原型链。
2.对象的原型
const obj = {}
console.log(obj.__proto__); // Object.prototype
console.log(obj.__proto__ === Object.prototype); // true
console.log(obj.prototype); // undefined
上面的代码我们通过字面量的方式创建了一个对象 obj ,而 __proto__ 是 obj 的原型,而 obj.__proto__ === Object.prototype,也就是说所有对象的原型最终都会指向 Object.prototype,而Object.prototype本身也是一个对象,那么它的原型是什么呢,我们知道原型链的终点是null,而 Object.prototype的原型正是指向原型链的终点 null,即:Object.prototype.__proto__ === null。还有一点对象是没有 prototype 属性的。
重点:JS中所有对象的原型最终都会指向
Object.prototype,而Object.prototype的原型等于null。
3.函数的原型
function fn() { }
console.log(fn.__proto__ === Function.prototype); // true
console.log(fn.prototype);
当函数被当作对象时,也可以说当函数不被用作构造函数时,它的原型是 __proto__,而不做构造使用的函数的原型最终都是指向 Function.prototype的,而 Function.prototype 是个对象,所以它的原型还是指向 Object.prototype,也就是 Function.prototype.__proto__ === Object.prototype。
tips:
Function的__proto__也等于Function.prototype。因为当Function不被当作构造函数使用时,那么它的原型__proto__也是指向Function.prototype的。
而当函数被用作构造函数时,它的原型就是 prototype,创建的实例都是从构造函数的 prototype 上去继承属性和方法的。
也可以说,函数都是由
Function原生构造函数创建的,所以函数的__proto__属性指向Function的prototype属性。
4.解析上面那张图
function Foo() { }
const f1 = new Foo()
console.log(f1.__proto__ === Foo.prototype); // true
console.log(Foo.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
const o1 = new Object()
console.log(o1.__proto__ === Object.prototype); // true
console.log(Object.prototype.constructor === Object); // true
console.log(Object.__proto__ === Function.prototype); // true
console.log(Function.prototype.constructor === Function); // true
这个代码基本上可以描述上面那张图的内容。
-
f1.__proto__ === Foo.prototypeFoo是当构造函数使用的,它的原型是prototype,所以实例的原型等于它,没问题,这里看不懂的可以去看下 new 构造函数内部做了什么事情。
-
Foo.prototype.__proto__ === Object.prototypeFoo.prototype是个对象,它的原型指向所有对象原型的终点Object.prototype。
-
Object.prototype.__proto__指向原型链的终点null。
-
o1.__proto__ === Object.prototype这个跟第2条是一样的。
-
Object.prototype.constructor === Object构造函数原型中的constructor属性指回构造函数。
-
Object.__proto__ === Function.prototype函数不做构造函数使用时它原型的终点是Function.prototype。
-
Function.prototype.constructor === Function跟第5条一样。