彻底搞清楚什么是原型链


theme: awesome-green

对象

要弄清楚原型链,首先要弄清楚对象

普通对象

  • 最普通的对象: 有__proto__属性(指向其原型链),没有prototype属性。
  • 原型对象(Person.prototype原型对象还有constructor属性(指向构造函数对象))
  • 函数对象 凡是通过new Function() 创建的都是函数对象

拥有__proto__, prototype属性(指向原型对象)

Function Object Array Date String 自定义函数

特例: Function.prototype(是原型对象,却是函数对象,下面会有解释)

 // 函数对象
function F1() {
};
var F2 = function () {
};
var F3 = function (n1, n2) {
 return n1 + n2
};

console.log(typeof F1);        // function
console.log(typeof F2);        // function
console.log(typeof F3);        // function
console.log(typeof Object);    // function
console.log(typeof Array);     // function
console.log(typeof String);    // function
console.log(typeof Date);      // function
console.log(typeof Function);  // function

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lXq7Zo78-1662564824944)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/30cbe8ae00ff4218bbcf55852fdd48dc~tplv-k3u1fbpfcp-watermark.image)]

Array是函数对象,是Function的实例对象,Array是通过new Function创建出来的,因为Array是Function的实例,所以Array.__proto__ === Function.prototype

// 普通函数
function F1() {}
let o1 = new F1();
let o2 = {};
let o3 = new Object();
console.log(typeof o1); // object
console.log(typeof o2); // object
console.log(typeof o3); // object

原型对象

每创建一个函数都会有一个prototype属性,这个属性是一个指针,指向一个对象(通过该构造函数创建实例对象的原型对象)。原型对象是包含特定类型的所有实例共享的属性和方法,原型对象的好处是,可以让所有实例对象共享它所包含的属性和方法。

第一块中有提到,原型对象属于普通对象,Function.prototype是个例外,它是原型对象,却又是函数对象,作为一个函数对象,它又没有prototype属性

function Person(){};  

console.log(typeof Person.prototype) //Object  
console.log(typeof Object.prototype) // Object  
console.log(typeof Function.prototype) // 特殊 Function  
console.log(typeof Function.prototype.prototype) //undefined 函数对象却没有prototype属性 

解释:

其实原型对象就是构造函数的一个实例对象。person.prototype就是person的一个实例对象。相当于在person创建的时候,自动创建了一个它的实例,并且把这个实例赋值给了prototype

function Person(){};  
var temp = new Person();  
temp.__proto__ == Person.prototype

function Function(){};  
var temp = new Function();  
Function.prototype = temp; //由new Function()产生的对象都是函数对象  

从一张图看懂原型对象、构造函数、实例对象之间的关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4YXtqihA-1662564824947)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3195f7f9546046509e33aa347e3f2143~tplv-k3u1fbpfcp-watermark.image)]

function Dog() {}
  Dog.prototype.name = '小黄';
  Dog.prototype.age = 12;
  Dog.prototype.getAge = function () {
    return this.age;
  }
  let dog1 = new Dog();
  let dog2 = new Dog();
  dog2.name = '小黑';
  console.log(dog1.name); // 小黄,来自原型
  console.log(dog2.name); // 小黑,来自实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NQJfcuDj-1662564824951)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/46db024f71074f3c9a2b02115dfb8b55~tplv-k3u1fbpfcp-watermark.image)]

//图中的一些关系  
dog1.__proto__ === Dog.prototype  
  
Dog.prototype.__proto__ === Object.prototype //继承Object 下面原型链说  
  
dog1.__proto__.__proto__ === Object.prototype  
  
Dog.prototype.constructor === Dog   
  
Dog.prototype.isPrototypeOf(dog1)  
  
//获取对象的原型  
dog1.__proto__  //不推荐  
Object.getPrototypeOf(dog1) === Dog.prototype   //推荐 

原型链

原型链是实现继承的主要方法。

先说一下继承,许多OO语言都支持两张继承方式:接口继承、实现继承。

|- 接口继承:只继承方法签名

|- 实现继承:继承实际的方法

由于函数没有签名,在ECMAScript中无法实现接口继承,只支持实现继承,而实现继承主要是依靠原型链来实现。

原型链基本思路:

利用原型让一个引用类型继承另一个引用类型的属性和方法。

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数想指针(constructor),而实例对象都包含一个指向原型对象的内部指针(__proto__)。如果让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针(__proto__),另一个原型也包含着一个指向另一个构造函数的指针(constructor)。假如另一个原型又是另一个类型的实例……这就构成了实例与原型的链条。

原型链基本思路(图解):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LNxVvdpz-1662564824952)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/23e349dac24e4734929cd147700b6242~tplv-k3u1fbpfcp-watermark.image)]
举例说明

function Animal(){  
    this.type = "animal";  
}  
Animal.prototype.getType = function(){  
    return this.type;  
}  
  
function Dog(){  
    this.name = "dog";  
}  
Dog.prototype = new Animal();  
  
Dog.prototype.getName = function(){  
    return this.name;  
}  
  
var xiaohuang = new Dog();  
//原型链关系  
xiaohuang.__proto__ === Dog.prototype  
Dog.prototype.__proto__ === Animal.prototype  
Animal.prototype.__proto__ === Object.prototype  
Object.prototype.__proto__ === null

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2f0U182u-1662564824953)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7554a111433844588bae90e54d798281~tplv-k3u1fbpfcp-watermark.image)]

详解图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BTaRd0i1-1662564824955)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bf90861612e449129442fa9125b26627~tplv-k3u1fbpfcp-watermark.image)]

图片修正:笔误,第一行应该是xiaohuang.__proto__ === Dog.prototype)

从xiaohuang这个实例,看出整个链条

总结:

Xiaohuang这个Dog的实例对象继承了Animal,Animal继承了Object。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值