类与实例
声明一个类:
/** ES5声明一个类**/
function Animail(){
this.name = 'name';
}
/** ES6声明一个类**/
class Animal2{
constructor(){
this.name = "name";
}
}
/** 实例化**/
new Animal()
new Animal2()
类与继承
第一种方式,借助构造函数实现继承
/** 借助构造函数实现继承**/
function parent1(){
this.name = "parent1"
}
function child1(){
parent1.call(this);//改变上下文,将父级构造函数指向到子级上
this.type='child1'
}
console.log(new Child())
第二种方式,借助原型链实现继承
/** 借助原型链实现继承**/
function parent1(){
this.name = "parent1"
}
function child1(){
this.type='child1'
}
child1.prototype = new parent1();//作用域由实例本身开始,向原型链上查找属性
console.log(new child1())
缺点:
如果两个实例同时用一个父类的原型,在修改原型链上的属性时,会导致另一个实例的值也会被更改,因为共用的一个父类实例在原型链上
第三种方式,组合方式实现继承
/** 组合方式实现继承**/
function parent1(){
this.name = "parent1"
}
function child1(){
parent1.call(this)//改变上下文,将父级构造函数指向到子级上
this.type='child1'
}
child1.prototype = new parent1();//作用域由实例本身开始,向原型链上查找属性
console.log(new child1())
缺点:父级构造函数被执行了2次
第四种方式,优化1组合方式
/** 组合方式实现继承**/
function parent1(){
this.name = "parent1"
}
function child1(){
parent1.call(this)//改变上下文,将父级构造函数指向到子级上
this.type='child1'
}
child1.prototype = parent1.prototype;//将父级原型对象赋值到子上
console.log(new child1())
缺点:child1的constructor指向的是parent,因为parent和child共用一个原型对象
第五种方式,优化2组合方式
/** 组合方式实现继承**/
function parent1(){
this.name = "parent1"
}
function child1(){
parent1.call(this)//改变上下文,将父级构造函数指向到子级上
this.type='child1'
}
child1.prototype = Object.create(parent1.prototype);//Object.create创建出来的原型对象就是参数(parent1的原型),而且达到了父类和子类原型对象的隔离
child1.prototype.constructor = child1;//将构造函数指向到实例的构造函数
console.log(new child1())
ES6继承方式
class Animal{
//构造函数
constructor(props){
this.name=props.name||'未知';
}
eat(){
alert(this.name+"在吃东西...");
}
}
//class继承
class Bird extends Animal{
//构造函数
constructor(props){
//调用实现父类的构造函数
super(props);
this.type=props.type||"未知";
}
fly(){
alert(this.name+"在飞...");
}
}