prototype
:原型__proto__
:原型链(原型的连接点)prototype
→ 函数的一个属性:这个属性是个普通对象 {}__proto__
→ 对象的一个属性:这个属性也是个普通对象 {}obj.__proto__ === Object.prototype
function Test() {
this.a = 1;
}
console.log(Test.prototype); // {constructor: Test}
const test = new Test();
console.log(test.__proto__); // {constructor: Test}
console.log('test.__proto__ === Test.prototype', test.__proto__ === Test.prototype); // true
// 由于我们说 对象是有一个 __proto__ 属性的,所以 Test.prototype 也应该有个 __proto__ ,因为本质上 Test.prototype 也是个对象
console.log("Test.prototype.__proto__ === Object.prototype", Test.prototype.__proto__ === Object.prototype); // true
// 而 Test.prototype 本质上是由 Object 构造函数生成的,所以 Test.prototype.__proto__ === Object.prototype
// 由于 Object.prototype 也是个对象,所以应该也有 __proto__ :
console.log(Object.prototype.__proto__); // null
// 但我们会发现,Object.prototype 就是原型链的顶层了,它的 __proto__ 值为 null
console.log(Object.prototype); // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
// 现在我们给 Test 构造函数中添加一个属性 a (新增的a在第 2 行),打印一下:
console.log(test); // Test {a: 1}
// 由于 Test.prototype 是个对象,我现在给这个对象上挂载一个属性b:
Test.prototype.b = 2;
// 再来打印下 test :
console.log(test);
// 那么 test.__proto__ 上就有了一个属性 b 。原因就是 test.__proto__ === Test.prototype,在 prototype 上加了个 b ,所以 __proto__ 上也就有 b
// 现在我们在 Object.prototype 上挂载一个 c :
Object.prototype.c = 3;
// 再来打印下 test :
console.log(test);
// 所以此时 Test.prototype.__proto__ 上也就有了个 c = 3
// 关系图如下:
/**
* test {
* a: 1,
* __proto__ = Test.prototype = {
* b: 2,
* __proto__ = Object.prototype = {
* c: 3,
* 没有 __proto__
* }
* }
* }
*/
// 总结:原型链就是 以一个对象为基准,以 __proto__ 为连接的链条,一直到 Object.prototype 为止 的这个链叫原型链
XXX.__proto__ === Function.prototype
__proto__
指向 Function.prototype:Function.__proto__ === Function.prototype
Function.__proto__ === Function.prototype
Object
构造函数本身也是对象,也有 Object.__proto__ === Function.prototype
// Function Object 这俩既是对象又是函数
// Test 这个函数是由 Function 构造出来的,也就是底层应该是 const Test = new Function(...)
console.log(Test.__proto__);
// 所以有:
console.log("Test.__proto__ === Function.prototype", Test.__proto__ === Function.prototype);
// 但是 Function 有不合理的地方,就是:
console.log('Function.__proto__ === Function.prototype', Function.__proto__ === Function.prototype); // true
// ⬆️ 底层就是这么规定的,如何理解:Function 就是顶层,它自己就是由自己构造的,它用自己的构造函数构造了自身
// 我们知道 Object 其实也是个函数,因为对象就是通过 new Object() 创建出来的:
// const obj = {};
// const obj = new Object();
console.log("typeof Object", typeof Object); // function
// 由于 Object 本身是个函数,所以这个函数本身是 Function 构造的:
console.log("Object.__proto__ === Function.prototype", Object.__proto__ === Function.prototype); // true
// 由上导出
console.log("Object.__proto__ === Function.__proto__", Object.__proto__ === Function.__proto__); // true
// 判断属性是否存在对象本身身上,而不是在 prototype 上:
console.log("test.hasOwnProperty('a')", test.hasOwnProperty('a')); // true
console.log("test.hasOwnProperty('b')", test.hasOwnProperty('b')); // false
console.log("test.hasOwnProperty('c')", test.hasOwnProperty('c')); // false
// 判断属性是否在对象的链条上:
console.log("'a' in test", 'a' in test); // true
console.log("'b' in test", 'b' in test); // true
console.log("'c' in test", 'c' in test); // true
Test.prototype.constructor === Test
test.__proto__.constructor === Test
// test.constructor -> 实例化test对象的构造函数
console.log("test.constructor === Test", test.constructor === Test);
console.log(test);
// Test
// __proto__:
// constructor: ƒ Test()
// __proto__: Object
// 注意:constructor是可以被改的
function Test1() {
this.a = 111;
}
test.constructor = Test1;
console.log(test.constructor === Test1); // true
https://player.bilibili.com/player.html?bvid=BV1ci4y157Ci&p=1&page=1