先给出名词的定义:
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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。