前言
最近实在是太空闲了,心态有些浮躁,无法让自己静下心来学习新的东西,写写博客打发时间,顺带总结复习前段时间学到的东西吧,也算是初步解决了从学习前端的一个大石头。
JavaScript中的原型
我们经常封装一个类,来创建许多具有相同方法的对象,去做不同的事情。比如说:
function Person(option) {
this.name = option.name
this.age = option.age
}
Person.prototype.eat = function(){
console.log("my name is "+this.name+",i can eat apple")
}
Person.prototype.sayHi = function(){
console.log("Hi,my name is "+this.name+",i'm "+this.age+" year's old")
}
我们写了一个Person类,Person类具有两个方法,所有通过这个类创建的对象都将拥有这两个方法
let man = new Person({
name:"xiaoming",
age:19
})
man.sayHi() // Hi,my name is xiaoming , i'm 19 year's old
man这个对象本身是没有sayHi方法的,这个sayHi方法是写在他的原型对象上的,也就是man的 __ proto __
这里的__ proto __指的便是我们之前所封装的Person类,里面有类的构造函数constructor,类的方法
而当我们在控制台打印Person的prototype,得到的是原型对象本身,也就是Person类,而Person本身是一个构造函数,可知
经过观察控制台我们发现,Person原型对象的原型对象是Object
原型对象的原型指向的是Object对象,即
Person.prototype = Object.prototype
又经过一轮观察发现,Person的构造函数的原型__ proto __指向的是Function对象
到这儿我们的原型图可以画成
这儿值得一提的是,Function对象的构造方法是由Function对象的构造方法实例化出来的,也就是Function.prototype.constructor==Function.prototype.constructor
即Function对象是由自己的构造函数构造出来的,而Function的原型对象是由Object对象的构造函数实例化出来的。
还有一个比较有意思的是,Object的构造方法是又Function构造方法构造出来的,Object构造方法自身也继承来着Function的原型对象属性和方法。
于是我们完整的原型链图为:
JavaScript的继承
JavaScript中,你调用对象的某个方法,解析机制会优先到对象身上去找这个方法,如果找不到,系统便会往对象的__proto__
上面去找,即对象的原型对象,如果原型对象身上也没有,那么就会到原型对象的原型对象上找,依旧找不到便会报错。
而这里这个原型对象的原型对象,这条关系链即为我们所说的原型链。
举个例子,我们都知道JavaScript中所有对象都是拥有toString()方法,因为toString()方法是挂在Object的原型对象上,而所有对象的原型对象最终的指向都是Object对象,即所有对象都拥有toString()方法。
同一个方法(这里比如toString),所有对象都有,但在不同类型的对象上的方法效果不同,原因在于,不同类型的对象,原型对象不同,他们各自的原型对象重写的方法,由于JavaScript解析机制的问题,会优先寻找到自身原型对象上重写的同名方法,所以方法表现便会不同。
不同对象的原型对象相同,不同对象可以调用来自同一个对象的方法,这便是JavaScript的继承。