面向对象
前言:面向对象是一种编程思想,基于这种思想,大大提高了代码的复用率。而在js中,用于es6之前并没有类的概念,而是提供了一个构造函数的概念,将原型prototype作为类的实现方法,导致js提出了众多的继承思想,以下列举一些典型的方法。
继承
1. 原型链继承
核心方法:将父类的实例作为子类的原型。
特点:
- 关系明确,实例不仅是子类的实例,也是父类的实例。
- 父类所有的以及添加的原型方法/原型属性,子类都可以访问到。
- 实现简单。
缺点:
- 来自原型对象的所有属性被所有实例共享。
- 无法实现多继承。(多继承指一个类可以继承多各类,如:A可以同时继承B类和C类)
// 推荐程度 ★☆☆☆☆
// 父类
function Father(){
this.lastName = 'Smith'
}
Father.prototype.getLastName = function(){
return this.lastName
}
// 子类
function Son(){
this.firstName = 'son'
}
Son.prototype = new Father()
Son.prototype.getFirstName = function(){
return this.firstName
}
var son = new Son()
console.log(son.firstName)
console.log(son.lastName)
console.log(son.getFirstName())
console.log(son.getLastName())
2. 构造函数继承
核心:call()方法是构造函数继承的精华所在。
call方法改变了函数的作用环境,因此只能继承父类实例中的属性和方法,不能继承原型对象上的方法
特点:
- 实例化子类时,可以向父类传递参数
- 能够实现多继承(可以call多个父类)
缺点:
- 不能继承原型属性及方法
// 推荐程度 ★★☆☆☆
// 父类
function Father(firstName){
this.firstName = firstName
this.lastName = 'Smith'
}
Father.prototype.getLastName = function(){
return this.lastName
}
// 子类
function Son(firstName){
Father.call(this,firstName)
}
var son = new Son('son')
console.log(son.firstName)
console.log(son.lastName)
console.log(son.getLastName()) // throw Error
3. 组合继承
这种继承即将原型继承以及构造函数继承结合起来,优点很明显,包含了两种继承方式的优点。
缺点也很明显,在子例构造函数继承时执行了一边父类的构造函数,原型继承时又调用了一遍父类的构造函数。重复调用
// 推荐程度 ★★★☆☆
// 父类
function Father(firstName){
this.firstName = firstName
this.lastName = 'Smith'
}
Father.prototype.getLastName = function(){
return this.lastName
}
// 子类
function Son(firstName){
Father.call(this,firstName)
}
Son.prototype = new Father()
var son = new Son('son')
console.log(son.firstName)
console.log(son.lastName)
console.log(son.getLastName())
4. 寄生组合式继承
核心:声明一个空的构造函数F,利用这个构造函数继承父类,子类再继承F的原型
// 继承方法 推荐程度 ★★★★☆
function inherit(Target,Origin){
function F (){ }
F.prototype = Origin.prototype
Target.prototype = new F()
Target.constructor = Target
}
// YUI3 闭包 推荐程度 ★★★★★
var inherit = (function(){
var F = function(){ }
return function(Target,Origin){
F.prototype = Origin.prototype
Target.prototype = new F()
Target.constructor = Target
Target.prototype.uber = Origin.prototype
}
})()
总结:虽然继承方法很多,但还是推荐最后两个,YUI3中还利用了闭包