先给出名词的定义:
1、实例对象 - 被 new 进去对象称之为实例对象
例如: const p1 = new Person()
p1 就是实例对象
2、一般对象 - 未经 new,间接申明的对象是一般对象
例如:const p2 = {name: "John"}
p2 就是一般对象
3、prototype,中文翻译:原型对象
4、__proto__,中文翻译:原型 (英文能够读作 dunder proto)
因为原型对象和原型容易混同,下文间接应用 prototype 和 _proto(__proto__的简写) 来行文,
为什么要理解 js 中的原型链:
JS 中没有类的概念,为了实现继承 (让一个实例对象领有不属于本身的属性或办法),通过 __proto__将实例对象和实例对象的 prototype 分割起来组成原型链,就能够让对象拜访到不属于本人的属性。
也就是说拜访一个实例 p1 的办法 A,这个实例 p1 上不存在,则通过 p1.__proto__上溯到 p1 构造函数 Person 的 prototype(即上溯到 Person.prototype),如果 Person.prototype 上仍然没找到办法 A,则在 Person.prototype 的_proto 上持续找,通过 Person.prototype.__proto__持续上溯 (Person.prototype.proto === Object.prototype)…
看上面的代码
function Person(name) {this.name = name;}
Person.prototype.sayHello = function() {console.log(`Hello, ${this.name}!`);
}
const p1 = new Person("Mike");
p1.sayHello(); // "Hello, Mike!"
console.log("Person.prototype->", Person.prototype);
console.log("p1.__proto__->", p1.__proto__);
console.log("getPrototypeOf(p1)->", Object.getPrototypeOf(p1));
console.log(Person.prototype === p1.__proto__); // true
下面这段代码的后果展现了:
对于一个构造函数,和通过构造函数 new 进去的对象,构造函数的 prototype 与实例对象的_proto 雷同。
注:
__proto__是非规范的属性,未在 ECMAScript 6 规范中定义,但简直所有的古代浏览器都反对 __proto__属性。为了规范性,能够应用 Object.getPrototypeOf(obj) 办法来获取对象的_proto。
再看上面这段代码
const p2 = {name: "John"};
console.log(p2.__proto__); // [Object: null prototype] {} -> 是一个空对象 {} console.log(p2.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
一般对象的_proto 值是 [Object: null prototype] {}
Object.prototype.__proto__ === null 这是原型链的重点
那么构造函数与 Object 有什么关联?
console.log(Person.prototype.__proto__ === Object.prototype); // true
其余:
1、prototype 属性只存在于函数上,而__proto__ 存在于所有对象上。
留 2 个问题
console.log(Object.__proto__ === Object.prototype); // true or false? why?
console.log(Function.__proto__ === Function.prototype); // true or false?
同步更新到本人的语雀
https://www.yuque.com/dirackeeko/blog/bggcmd8fcib3uyvt