最近在复习js的基础知识,今天准备学习的是js原型链,那在介绍js原型链之前先看一段代码。
function Person() {
} // 一个构造函数
let person1 = new Person();
let person2 = new Person();
Person.prototype.name = 'koala';
console.log(person1.name) // koala;
console.log(person2.name) // koala;
如上,有一个构造函数Person,并new了两个实例对象,person1、person2;
在构造函数的实例原型上增加了name属性,则构造函数生成的两个实例,也会找到name的属性,并且值为koala。
prototype
每个构造函数都会有prototype属性,它指向的是构造函数创建的实例的实例原型,在上面的例子中,也就是person1、person2的原型。如何理解实例原型呢?每一个javascript对象(null除外)的生成,都会产生与之关联的一个另一个对象,这个对象就是原型,每一个对象都会从原型"继承"属性。
需要注意的是proptotype是只有函数才会有的属性
用一张图直观的表示构造函数和实例原型的关系:
在了解了构造函数和实例原型的关系后,我们来想想,实例和实例原型的关系如何关联呢?
_ proto_
每个对象都会有__proto__属性,对象的__proto__属性指向对象的实例原型。
需要注意的是__proto__是只有对象才会有的属性
function Person(){}
let person1 = new Person();
console.log(person1.__propto__ === Person.prototype) // true
在了解了实例和实例原型之间的联系后,我们思考一下,实例原型可以指回实例和构造函数吗?因为构造函数会生成多个实例,所以没有实例原型可以指回实例,但是实例原型可以通过constructor属性指回构造函数。
constructor
每一个实例原型都有一个constructor属性指向与之关联的构造函数。
function Person() {};
console.log(Person.prototype.constructor === Person); // true;
//介绍一个es5的方法Object.getPrototypeOf(obj):获取obj对象的原型。
console.log(Object.getProttypeOf(person) === Person.proptotye) // true;
以上内容介绍了实例,实例原型,构造函数之间的关系。接下来将为大家介绍一下实例和实例原型之间的联系。
function Person(){}
let person1 = new Person();
Person.prototype.name = 'koala2';
person1.name = 'koala1';
console.log(person1.name); // koala1;
delete person1.name;
console.log(person1.name); // koala2;
在这个例子中,实例person1的属性被删除后,实例就会向它的原型去查找属性,原型也是对象,既然是对象那么原型也有原型,如果在原型上查找不到属性,就会向原型的原型上查找,如法炮制,那原型的原型是什么呢?
原型的原型
在前面,我们已经讲了原型也是一个对象,既然是对象,我们就可以用最原始的方式创建它:
let obj = new Object();
其实原型对象就是通过 Object 构造函数生成的,那 Object.prototype 的原型呢?
null
我们可以打印:
console.log(Object.prototype.proto === null) // true
然而 null 究竟代表了什么呢?
null 表示“没有对象”,即该处不应该有值。
所以 Object.prototype.proto 的值为 null 跟 Object.prototype 没有原型,其实表达了一个意思。
所以查找属性的时候查到 Object.prototype 就可以停止查找了。
最后一张关系图也可以更新为: