js继承方式
js是一门弱类型动态语言,封装和继承是他的两大特性
原型链继承
优点:
- 简单易于实现
- 实例是子类的实例,实际上也是父类的一个实例
- 父类新增原型方法、原型属性,子类都能访问到
缺点:
- 所有子类的实例的原型都共享同一个超类实例的属性和方法
- 无法实现多继承
- 在创建子类的实例时不能向父类的构造函数传递参数
父类
function animal(){
this.name=name||"animal"
this.sleep=function(){
console.log(this.name+"正在睡觉!")
}
}
animal.prototype.eat=function(food){
console.log(this.name+"正在吃"+food)
}
子类
function cat(){}
cat.prototype=new animal()
cat.prototype.name="cat";
var cat=new cat();
console.log(cat.name); // cat
console.log(cat.eat('fish')) // cat正在吃fish undefined
console.log(cat.sleep()) // cat正在睡觉 undefined
console.log(cat instanceof animal) // true
console.log(cat instanceof cat) // true
构造继承
通过使用call、apply方法可以在新创建的对象上执行构造函数,用父类的构造函数来增加子类的实例
1、拿不到父类中prototype中的对方和方法,无论是在调用apply()之前还是之后
2、父类中公有的对象/方法都通过this传递,每new一个实例都需要储存this的内容,耗费内存
function Person(name, age) {
this.name = name;
this.age = age;
this.type = 'person';
}
// 用apply调用Person,this(Student)代替Person的this,
//达到继承Person的对象和方法的目的
function Student(name, age, grade) {
Person.apply(this, arguments);
this.grade = grade;
}
var student = new Student("zhangsan", 21, "一年级");
console.log('student:', student.type) // student: person
组合继承
function F() {
// 属性
this.name = name || 'Animal';
// 实例方法
this.sleep = function(){
console.log(this.name + '正在睡觉!');
}
}
function C(name){
F.call(this);//构造函数继承
this.name = name || 'Tom';
}
C.prototype = new F();//原型继承
var q=new C();
console.log(q.name); // Tom
console.log(q.sleep()); // Tom正在睡觉
ES6继承
继承会继承父类的实例属性和实例方法,并不会继承静态属性和静态方法,并且静态方法只能通过类名去调用
class father{
constructor(name){
this._name=name
}
getName(){
console.log(this._name)
}
static jingtai(){
console.log("静态")
}
}
class son extends father{
constructor(name,age){
super(name)
this._age=age
}
}
var father=new father("小红")
father.jingtai(); // 静态
father.getName() // 小红
var xiaoming=new son('小明',15)
xiaoming.getName() // 小明
//子集只会继承父类的实例属性和方法,不会继承静态属性和静态方法
//静态方法只能通过类名去调用
网友评论