一、 构造函数
构造函数的目的就是为了创建一个自定义类,并且创建这个类的实例。构造函数需要用new关键字来调用。
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
this.sayName = function () {
alert(this.name);
}
}
var per = new Person("孙悟空", 18, "男");
每执行一次Person构造函数,就会创建一个新的sayName方法。也就是说构造函数执行1000次,就会创建1000次新方法,而这些方法是一模一样的。为什么不把这个方法单独放到一个地方,并且让所有的实例都能访问到呢?
这就是需要原型(prototype)
二、 原型
在JavaScript中,每当定义一个函数数据类型(普通函数,类)时候,都会自带一个prototype属性,来指向函数的原型对象,并且这个属性是一个对象数据类型的值。
(原型对象相当于一个公共区域,同一个类的所有实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中)。
三、 原型链
1.prototype、__proto__和constructor
每一个对象数据类型(普通的对象、实例、prototype…)也天生自带一个属性__proto__,属性值是唐倩实例所属类的原型(prototype)。原型对象中有个属性constructor,它指向函数对象。
2.何为原型链
在javascript中万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,是通过prototype对象指向父类对象,知道指向Object对象为止,这样就形成了一个原型指向的链条,叫做原型链。
举例说明:person -> Person -> Object
当我们访问一个对象的一个属性或方法时,如果自身有就直接使用,如果没有就会到原型对象里寻找,如果找到就会使用,如果没有就会到原型的原型中寻找,直到找到Object对象的原型,Object的原型中没有找到,则返回undefined。(Object是所有对象数据类型的基类,在Object.prototype上没有__proto__这个属性)
class Animal{
constructor(type){
this.type = type
}
}
class Human extends Animal{
constructor(race){
super('human')
this.rece = race
}
}
class Person extends Human{
constructor(name){
super('yellow')
this.name = name
}
}
let animal = new Animal('dog')
let person = new Person('小星')
console.log(person) //Person { type: 'human', rece: 'yellow', name: '小星' }
console.log(person.__proto__ === Person.prototype) //true
console.log(person.__proto__.__proto__ == Human.prototype) //true
console.log(Animal.prototype.constructor == Animal) //true
console.log(animal.__proto__== person.__proto__.__proto__.__proto__) //true