今天在回学校的路上一直在看《JavaScript 高级编程设计》第六章的内容(面向对象的程序设计)。
发现自己致命的缺点,确实是JavaScript的知识掌握的不够深入,真的是有幸读到这本书,好了废话不多说。
要说原型链就不得不说继承,这两者基本很难分开。
假设你已经知道什么是原型,什么是原型对象,什么是实例对象,什么是构造器(constructor),什么是构造函数了。
那么可以列出下面
由上图我们可以知道上面提到的五样的区别。我们可以知道实例是通过 new 出一个构造函数获得的,而构造函数中存在一个prototype属性也就是原型,它所引用的对象叫做原型对象,原型对象包含着一个构造器指着构造函数。
每当代码运行到某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从实例对象开始,如果实例对象中存在这个属性,则会返回该属性;但是如果搜索完这个实例对象没找到这个属性,则会顺着原型(prototype),在原型对象中找这个名字的属性,存在则返回该属性,否则返回undefined。
function Person(){ // 构造函数
this.name = 'yang';
}
Person.prototype.age = 22; // 给原型对象添加属性
Person.prototype.sex = 'male';
var person1 = new Person(); //创建实例对象
console.log(person1.name,person1.age,person1.sex); // yang ,22, male
由上面的代码:当我们创建出实例之后,打印name的属性可以直接得到‘yang’,打印age与sex,因为它的构造函数中没有这两个属性,所以它会顺着原型搜索,在prototype中我们设置好age 与 sex,所以将会打印出 22,与‘male’。
通过这种机制,我们可以试着将不同的对象通过原型将他们串联起来。
function Person() { // 构造函数
}
Person.prototype.speak = function () {
console.log(`i'm ${this.name}`)
}
function Man(name) {
this.name = name;
this.sex = 'male';
}
Man.prototype = new Person(); // 将Person的实例传给 Man的原型
Man.prototype.constructor = Man; // 注意之后Man的原型对象是一个Person的实例,这个原型对象的构造器属性指
// 向的是Person的构造函数,所以要将构造器指回Man
let man1 = new Man('yang');
man1.speak();
代码分析:首先我创建了两个构造函数 分别是 Person 和 Man,两个构造函数各有各的属性。接下来我将创建出来的Person实例赋值给了Man的原型,这样当我们实例出man1的对象,当代码运行到man1.speak(),首先会检索Man构造函数中是否存在speak属性,由于不存在,所以它会顺着原型找到Person的实例对象(内部存在指向Person.prototype的指针)从而继续检索到Person的原型。意思就是说原本存在于Person中的所有属性与方法,现在都在 Man.prototype 中了,这样就通过原型链实现了继承了。