基本概念
我理解的原型、原型链如下:
- 每个构造函数都有一个原型prototype,这个原型是对象,该对象里面存放着一些属性以及方法。这些属性和方法全部都会被构造函数创建的实例所共享。
- 当这个被构造函数创建的实例对象在自身找不到对应的属性或者方法时候会去它的原型上找,也就是创建它的构造函数的原型,具体是通过__proto__或者Object.getProtoTypeOf(obj)获得。
- 如果该实例的原型上没有找到对应的属性和方法,就会去prototype的原型上找,最终会找到Object.prototype,而Object.prototype的原型是null,这个寻找的过程也就是我们所说的原型链,常见的判断数据类型instanceOf方法就是依据这个原理去查找对象的原型链上是否存在构造函数的prototype。
如何访问原型
-
prototype
-
_proto
-
instanceof
-
isPrototypeOf
-
getPrototypeOf
-
setPrototypeOf
三角关系
对象,原型,构造函数这三者会形成一个三角关系,具体如下图所示:
- obj.constructor=constructor
- constructor.prototype=prototype
- obj.proto=prototype
- Object.getPrototype(obj)=prototype
- prototype.proto=Object.prototype
- Object.prototype.proto=null
理解这块内容的时候要注意,构造函数Fn比较特殊,Fn相当于生了自己和Object。 Fn.prototype.__proto__是Object.prototype,最终指向null Object.__proto是Fn.prototype
举例toString()
最常见的toString()方法是转为字符串,但是我们用Object.prototype.toString.call(obj)可以判断具体数据类型,那么为什么直接调用toString()不能判断呢?原因如下:
-
对象上的toString()方法作用是转为字符串,而Object原型上toString()才是判断具体数据类型,这时候该对象的原型链上就存在两个toString()方法,当我们直接调用的时候会先去自身查找,如果找到了就不会再继续沿着原型链向上查找,所以获取到的是改写后的toString()方法。通过这个例子就可以更好的理解原型链的概念。
原型相关的继承
- 原型链继承:不能传参,共享原型修改后相互影响
- 原型式继承:Object.create(obj),共享原型属性,不能传参,共享原型修改后相互影响。
function(obj){
Fn(){}
Fn.prototype = obj
return new Fn()
}
let son = function(new Father)