持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
结论:prototype 指向函数的原型对象,__proto__ 是指针。原型链则是通过 __proto__ 指向其原型对象,串联起链表。主要解决对象的继承问题。
什么是原型 prototype
JS 中的函数也是对象。如何证明函数也是对象?函数作为表达式被创建,并且可以添加任意的属性。
function fn() {}
fn.sex = 'male'
console.log(fn.sex) // male 函数可以添加任意的属性
// 利用 Object.create 方法,这个方法只有对象才能使用
function fn() {}
const obj = Object.create(fn);
// Object.create('') 则会报错,报错内容: Object prototype may only be an Object or null
console.log(Object.getPrototypeOf(obj) === fn); // true
在 JS 中,每当定义一个对象的时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个 prototype 属性,这个属性指向函数的原型对象。
使用原型对象的好处是所有对象实例共享它所包含的属性和方法。在做构造函数的时候经常会用到这个特性。
什么是原型链?什么是__proto__
__proto__是指针。原型链则是通过__proto__串联起来的链表。主要解决对象的继承问题。
先来看一段代码:
function Parent (name) {
this.name = name
}
Parent.prototype.showName = function() {
console.log(this.name)
}
const p = new Parent('kane')
p.showName()
console.log(p.__proto__ === Parent.prototype) // true
构造函数 Parent、Parent.prototype 和 实例 p 之间的关系:
每个实例对象都拥有一个原型对象,通过 __proto__ 指向其原型对象,并从中继承方法和属性。
同时原型对象也可能拥有他的原型对象,这样一层一层,最终指向 null(Object.proptotype.__proto__ 指向的是 null)。这种关系被称为原型链 (prototype chain)。
通过原型链,一个对象可以拥有定义在其他对象中的(继承过来的)属性和方法。
prototype 和 __proto__ 区别是什么?
prototype 是构造函数的属性。
__proto__ 是每个实例都有的属性,可以访问 [[prototype]]。
实例的 __proto__ 与其构造函数的 prototype 指向的是同一个对象。
function Parent (name) {
this.name = name
}
Parent.prototype.showName = function() {
console.log(this.name)
}
const p = new Parent('kane')
p.showName()
console.log(p.__proto__)
console.log(Object.getPrototypeOf(p))
console.log(Parent.prototype);
console.log(p.__proto__ === Parent.prototype) // true
class Human {
constructor(name) {
this.name = name;
}
say() {
console.log('hello');
}
}
class Man extends Human {
constructor(name) {
super(name);
}
run() {
console.log('running')
}
}
const man = new Man('kane')
man.say()
man.run()
console.log(Object.getPrototypeOf(man) === Man.prototype) // true
console.log(Object.getPrototypeOf(man) === Human.prototype) // false
如何实现 instanceof
特点
- 可以准确的判断复杂数据类型,但是不能正确判断基本数据类型
- 在原型链上的结果未必准确
- 不能检测
null,undefined。
通过原型链判断的,A instanceof B:
- 在 A 的原型链中层层查找,是否有原型等于
B.prototype。 - 如果一直找到 A 的原型链的顶端 (
null; 即Object.prototype.__proto__), 仍然不等于B.prototype,那么返回 false,否则返回 true。
// L instanceof R
function myInstanceOf(L, R) {// L 表示左表达式,R 表示右表达式
let O = R.prototype;// 取 R 的显式原型
L = L.__proto__; // 取 L 的隐式原型
// L = Object.getPrototypeOf(L) // 获取对象的原型
while (true) {
if (L === null) // 已经找到顶层
return false;
if (O === L) // 当 O 严格等于 L 时,返回 true
return true;
L = L.__proto__; // 继续向上一层原型链查找
}
}
let a = [1,2,3]
console.log(myInstanceOf(a, String)); // false