对js中的原型,原型链的理解

参考自:https://www.cnblogs.com/ningyn0712/p/6216711.html

javascript语言是一种面向对象的语言,它没有"子类"和"父类"的概念,里面所有的数据类型都是对象,js通过原型链将这些联系起来。

构造函数是一种特殊的方法,主要用来在创建对象时初始化对象。每个构造函数都有prototype(原型)(箭头函数以及Function.prototype.bind()没有)属性, 这个prototype(原型)属性是一个指针,指向一个对象,这个对象的用途是包含特定类型的所有实例共享的 属性和方法,即这个原型对象是用来给实例对象共享属性和方法的。每个实例对象的__proto__都指向这个 构造函数/类的prototype属性。

什么是原型链?当对象查找一个属性的时候,如果没有在自身找到,那么就会查找自身的原型,如果原型还没有找到,那么会继续查找原型的原型,直到找到 Object.prototype 的原型时,此时原型为 null,查找停止。 这种通过 通过原型链接的逐级向上的查找链被称为原型链 
链接:https://juejin.cn/post/6934500357091360781

1、首先了解一下构造函数

构造函数是用来创建特定类型的对象。

先定义一个People的构造函数

function People(name){
    this.name = name;
    this.sex = 'male'
}
// 通过new命令来生成两个个person实例
const person1 = new People()
const person2 = new People()
person2.sex = 'nv';
console.log(person1.sex)      // male 
console.log(person2.sex)      // nv
// 此时,People就是实例对象person1和person2的原型。

new出来的person1对象此时已经和Female再无联系了!也就是说每一个new出来的实例都有自己的属性和方法的副本,是独立的的!修改其中一个不会影响另一个!

此时,People就是实例对象person1和person2的原型, 理解为person1和person2是被People创建出来的。

说A是B的原型,必有B.__proto__ === A.prototype;

若我们希望给每个实例对象增加一个eyesColor属性,且通过People生成的实例中

eyesColor = 'red';

那么原型对象就即将登场了!给每一个构造函数都设置一个prototype属性,这个属性就指向原型对象。其实原型对象就只是个普通对象,里面存放着所有实例对象需要共享的属性和方法!所以,我们把需要共享的放到原型对象里,把那些不需要共享的属性和方法存在在构造函数里!

People.prototype.eyesColor = 'red';
console.log(person1.eyesColor)      // red 
console.log(person2.eyesColor)      // red
 // 实例一旦创建出来就会自动引用prototype对象的属性和方法!所以实例对象的属性和方法一般分为两种:一种是自身的,一种是引用自prototype的。
2、原型链的理解

当找某个对象的某个属性的时候,首先从对象实例本身开始,如果在实例中找到了该属性,则返回该属性的值,如果没有找到,则顺着原型链指针向上,到原型对象中去找。

 

这里要提一点,如果为对象实例添加了一个属性与原型中同名,则该属性会屏蔽掉原型中的同名属性,不会去修改它!使用delete可以删除实例中的属性~(提到delete那要插一句~delete只能删除对象下的属性,不能删除变量和参数!)

   __proto__:事实上就是原型链指针!!

prototype:上面说到这个是指向原型对象的

constructor:每一个原型对象都包含一个指向构造函数的指针,就是constructor

__proto__会指向上一层的原型对象,而上一层的结构依然类似,那么就利用__proto__一直指向Object的原型对象上!Object.prototype.__proto__ = null;表示到达最顶端。如此形成了原型链继承。

1、B由A创建,必有B.__proto__ === A.prototype;

2、A.prototype是原型对象,也是对象。

3、Object是作为众多new出来的实例的基类

4、Function是作为众多function出来的函数的基类

5、构造函数的__proto__(包括Function.prototype和Object.prototype)都指向Function.prototype

6、原型对象的__proto__都指向Object.prototype

7、Object.prototype.__proto__指向null

由上面7条规则,可容易理解下面关于原型链指针和原型对象的关系。

//代码1
function People(){}
var p = new People()
1 p.__proto__ === People.prototype 
//People函数创建了对象 p,所以People.prototype === p.__proto__;
2 People.__proto__ === Function.prototype
//People 作为对象的角色被函数Function创建,
所以 Function.prototype === People.__proto__
3 People.prototype.__proto__ === Object.prototype
//Object函数创建了People.prototype对象,
所以Object.prototype === People.prototype.__proto__;
4 Function.prototype === Function.__proto__  
//任何函数都是 Function 创建,所以Function 创建了 Function,
所以 Function.prototype === Function.__proto__;
5 Function.prototype === Object.__proto__ 
//Object 也是函数。所以Function创建了Object,
所以 Function.prototype === Object.__proto__ ;         
6 Function.prototype.__proto__ === Object.prototype 
//Function.prototype 是普通对象,普通对象是由Object创建的,
所以 Function.prototype.__proto__ === Object.prototype
7 Function instanceof Object
//instanceof 的作用是判断一个对象是不是一个函数的实例。
obj instanceof fn, 实际上是判断fn的prototype是不是在obj的原型链上

 

 

 

 

posted @ 2021-02-23 20:38  香香香。。。。香菜  阅读(86)  评论(0编辑  收藏  举报