原型和原型链和继承的理解

80 阅读3分钟

一、原型

理解原型,就要从理解构造函数开始。构造函数就是一个普通的函数,创建构造函数的方式和普通函数一样,但与普通的函数不一样,普通函数是直接调用的,而构造函数是通过new来调用的。
定义一个构造函数:

function Person(name) {
  this.name = name
  this.age = 18
}

通过new来创建一个对象:

var person1 = new Person('wecle')
console.log(person1.name)  //wecle

在这里,构造函数Person就是实例对象person1的原型,new出来的person1对象和Person已经没有联系了,person1继承了Person的属性和方法,也就是说person1也有name和age属性,所以每一个new出来的实例对象都有自己的属性和方法的副本。但这样的话,每new一个对象,就会创建一次新的副本,如果我们希望构造函数中的age属性是一个共有的属性,那么此时每个实例中都会有一个相同的age属性,这样会造成资源的浪费。

所以为什么不把这个属性放到一个单独的地方,让所有实例都能访问到呢?

这时候就需要原型(prototype)了

在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。

其实原型就只是个普通对象,里面存放着所有实例对象需要共享的属性和方法,所以就可以把需要共享的属性和方法放在原型对象里,把不需要共享的放在构造函数里。

function Person(name){
   this.name = name;
}
Person.prototype.age = 18;

var person1 = new Person("wecle");
var person2 = new Person("wwwww");
        
console.log(person1.age)
console.log(person2.age)

Person.prototype.age = 20;

console.log(person1.age)
console.log(person2.age)

具体实现方法:
每当代码读取某个对象的某个属性的时候,都会执行一次搜索。首先从对象实例本身开始,如果在实例中找到了该属性,则返回该属性的值,如果没有找到,则顺着原型链指针向上,到原型对象中去找,如果如果找到就返回该属性值。

2、原型链和继承

什么是原型链:只要是对象就有原型, 并且原型也是对象, 因此只要定义了一个对象, 那么就可以找到他的原型, 如此反复, 就可以构成一个对象的序列, 这个结构就被称为原型链
所有的实例有一个内部指针,指向它的原型对象,并且可以访问原型对象上的所有属性和方法。

image.png

复制代码
//定义一个 Animal 构造函数,作为 Dog 的父类
function Animal () {
    this.superType = 'wangcai';
}

Animal.prototype.speak = 'wangwang'

function Dog () {
    this.name ='zhuzhu'; 
}
//给Dog对象添加一个_ proto_,指向一个 Animal 实例
Dog.prototype = new Animal();

//再创建一个实例 Pig 
var Pig = new Dog() 

//Pig继承了Dog 和Animal的属性
console.log(Pig.speak) //wangwang

整个 Pig 对象是这样的

image.png