对js中的原型,原型链的理解
参考自:https://www.cnblogs.com/ningyn0712/p/6216711.html
javascript语言是一种面向对象的语言,它没有"子类"和"父类"的概念,里面所有的数据类型都是对象,js通过原型链将这些联系起来。
什么是原型链?当对象查找一个属性的时候,如果没有在自身找到,那么就会查找自身的原型,如果原型还没有找到,那么会继续查找原型的原型,直到找到 Object.prototype 的原型时,此时原型为 null,查找停止。 这种通过 通过原型链接的逐级向上的查找链被称为原型链
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的原型链上