在ES6之前并没有类的概念,而是通过构造函数来创建实例。
构造函数:
function Animal(name, age) {
this.name = name;
this.age = age;
this.sing = () => {
console.log('这是方法!')
}
}
如上所示,这就是一个构造函数,他可以用来创建对象,需要使用new关键词。
var dog = new Animal('狗蛋', '3个月');// new了一个对象,对象名字是dog
console.log('这是dog的名字:' + dog.name)// 这是dog的名字:狗蛋
console.log('这是dog的年龄:' + dog.age)// 这是dog的年龄:3个月
dog.sing();// 这是方法!
通过new关键字创建的对象,有构造函数中的所有属性和方法。所以dog有name也有age还能sing。
这时候,你可能想要给Animal这个构造函数增加一些动物都有的方法和属性,希望Dog这个实例也会有这些方法和属性。
Animal.sex = '公';
Animal.run = () => {
console.log('跑!')
}
dog.run();//run is not a function
console.log(dog.sex)// undefined
这时候就会发现如果用dog调用run方法和访问sex属性就会出现问题,这是因为Animal.sex和Animal.run定义的是Animal这个构造函数的私有属性和方法,是Animal独有的。(可以去看一下new的过程,面试经常考)
如果想要dog也能调用run的方法,就需要给Animal的原型添加方法和属性。
Animal.prototype.sex = '公';
Animal.prototype.run = () => {
console.log('跑')
}
console.log(dog.sex)// 公
dog.run();// 跑
如上所示,Animal.prototype就指向了Animal这个构造函数的原型,让我们看看这个原型里面都是什么。
就是我们之前定义的run方法和sex属性,还有constructor和__proto__
所以,构造函数的prototype可以添加一些公共的属性和方法,让他的实例也可以访问到。
那dog这个实例对象里面有什么呢?
发现里面并没有run这个方法和sex属性,但是点开__proto__发现,里面有sex和run。
这时候就会想,run的__proto__是不是等于Animal的。pro totype?尝试一下会发现,他们是全等的。所以,实例对象的__proto__指向了构造函数原型prototype。
同时,我们还能发现有个constructor(构造器),它的值好像是Animal,那我们就可以看一下dog. __ proto__.constructor是不是等于Animal。答案也是true,所以对象实例的__proto__的constructor指向了构造函数本身。
然后再一级一级地下去.