class Animal {//创建Animal类
constructor(species) { //constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。
this.species = species //Animal类 自己定义了species 属性
}
eat() { //Animal类 自己又定义了eat 方法
console.log('eateat')
}
static isAnimal() { //静态方法需要 static 修饰
console.log('i don\'t know ')
}
}
class Lion extends Animal {//创建Lion类
constructor(species, size) { //constructor方法如果没有显式定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。
// return new Animal();// 这里没有用this哦,直接返回一个全新的对象
super(species)//继承父类的属性,必须写在任何this的开头,不然会报错
this.size = size // Lion类 自己又定义了size 属性
// 继承和定义属性都在 构造函数 constructor 中继承或定义
}
eat() {//重写原型方法
console.log('eatmeat')
}
}
let lion = new Lion('Feline family', 'big')
let animal = new Animal('Feline big')
console.log(lion.species) //继承了父类的属性
console.log(lion.size) //Lion类的属性
Animal.isAnimal() //isAnimal方法是静态方法, Animal类中有这个方法,所以能调用,animal 实例调用不了 animal.isAnimal() 会报错
Lion.isAnimal() //isAnimal方法是静态方法, Lion 类中继承了这个方法,所以能调用,lion 实例调用不了 lion.isAnimal() 会报错
// animal.isAnimal() //Uncaught TypeError: animal.isAnimal is not a function
// lion.isAnimal() //Uncaught TypeError: lion.isAnimal is not a function
// 类的所有方法都定义在类的prototype属性上面,所有类中定义的方法都会被实例继承,如果在类方法前面加上static关键字就不会被实例继承了。
// 静态方法是直接通过类名来调用。Animal.isAnimal() Lion.isAnimal() 能调用成功
// Animal.eat() //类的所有方法都定义在类的prototype属性上面, Animal.eat() 调用会报错
// Lion.eat() // 类的所有方法都定义在类的prototype属性上面, Lion.eat() 调用会报错
lion.eat() //eatmeat
animal.eat() // eateat
//constructor中定义的属性可以称为实例属性(即定义在this对象上),constructor外声明的属性都是定义在原型上的,可以称为原型属性(即定义在class上)。hasOwnProperty()函数用于判断属性是否是实例属性。其结果是一个布尔值,true说明是实例属性,false说明不是实例属性。in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。
console.log(lion.hasOwnProperty("size"));//true
console.log(lion.hasOwnProperty("size"));//true
console.log(lion.hasOwnProperty("eat"));//false
console.log("size" in lion);//true
console.log("size" in lion);//true
console.log("eat" in lion);//true
console.log("eatSize" in lion);//false
//类的所有实例共享一个原型对象,它们的原型都是Person.prototype,所以proto属性是相等的
var lion2 = new Lion('Feline family2', 'big2')
console.log(lion.__proto__ === lion2.__proto__);//true
//由此,也可以通过proto来为类增加方法。使用实例的proto属性改写原型,会改变Class的原始定义,影响到所有实例,所以不推荐使用!
// 另外要理解的两点:1.实例属性指的是在构造函数方法中定义的属性和方法,每一个实例对象都独立开辟一块内存空间用于保存属性和方法。
// 2.原型属性指的是用于创建实例对象的构造函数的原型的属性,每一个创建的实例对象都共享原型属性。