ES6的类与继承与ES5的类与继承相比较
class 类
创建一个
Animal
类
ES6
- ES6中类的创建变得非常简单
class Animal {}
注:class
中的静态变量可以被枚举,function
中的静态变量不可以被枚举。方法都不可以被枚举.
class
创建的构造函数的原型里的方法是不能被实例枚举,但function
可以。属性都可以枚举。
ES5
function Animal() {}
constructor 构造器
新的构造器,为
Animal
类加上species
构造属性
ES6
class Animal {
constructor(species){
this.species = species
}
}
ES5
function Animal() {
this.species = species
}
为原型加上方法
为
Animal
的原型加上eat
方法
ES6
class Animal {
constructor(species){
this.species = species
}
eat(){//直接在class中写,将class看成function就行,里面的方法可以省略function
console.log('eateat')
}
}
ES5
function Animal(species) {
this.species = species
}
Animal.prototype.eat = function() { console.log('eateat') }
static 静态方法
为
Animal
类加上isAnimal
静态方法
ES6
class Animal {
constructor(species){
this.species = species
}
eat() {
console.log('eateat')
}
static isAnimal() {//静态方法需要 static 修饰
console.log('i don\'t know ')
}
}
ES5
function Animal(species) {
this.species = species
function isAnimal() {//加上静态方法
console.log('i don\'t know ')
}
}
Animal.prototype.eat = function() { console.log('eateat') }
extends 和 super
创建
Lion
类继承于Animal
类
ES6
class Animal {
constructor(species){
this.species = species
}
eat() {
console.log('eateat')
}
static isAnimal() {
console.log('i don\'t know ')
}
}
class Lion extends Animal{//创建Lion类
constructor(species, size){
super(species)//继承父类的属性,必须写在任何this的开头,不然会报错
this.size = size
}
eat() {//重写原型方法
console.log('eatmeat')
}
}
let lion = new Lion('Feline family','big')
ES5
//创建Animal类
function Animal(species) {
this.species = species
}
Animal.isAnimal() {
console.log('i don\'t know ')
}
Animal.prototype.eat = function() { console.log('eateat') }
//创建Lion类继承自Animal类
function Lion(species, size) {
Animal.call(this,species)//继承属性
this.size = size
}
Lion.__proto__ = Animal
//创建一个原型是Animal的原型的对象作为Lion的原型,extends干的事
Lion.prototype = Object.create(Animal.prototype)
Lion.prototype.conostructor = Lion
//重写eat方法
Lion.prototype.eat = function() { console.log('eat meat') }
//实例化对象
let lion = new Lion('Feline family','big')
注:为什么不用Object.setPrototype,在MDN上是这么说的
警告: 由于现代 JavaScript 引擎优化属性访问所带来的特性的关系,更改对象的 [[Prototype]]在各个浏览器和 JavaScript 引擎上都是一个很慢的操作。其在更改继承的性能上的影响是微妙而又广泛的,这不仅仅限于 obj.proto = … 语句上的时间花费,而且可能会延伸到任何代码,那些可以访问任何[[Prototype]]已被更改的对象的代码。如果你关心性能,你应该避免设置一个对象的 [[Prototype]]。相反,你应该使用 Object.create()来创建带有你想要的[[Prototype]]的新对象。
翻译成人话就是更改一个对象的原型比创建一个带有相应原型的对象性能上更差
,具体为什么性能更差,有没有大佬说说。
最后就写一个_new
方法实现new
的功能吧。
new
的功能
- 实例化类
- 继承类的原型
//传入需要实例化的类和实例化需要的参数,因为不确定参数个数,所以用`...`可变参数
function _new(cons, ...param) {
//创建绑定构造函数对象的原型的对象
let obj = Object.create(_class.prototype)
//执行构造函数
let result = cons.apply(obj, param)
//返回对象,如果构造函数 return 了一个对象,则返回构造函数 return 的
return result instanceof Object ? result : obj
}
如果传的参数个数为0个,params会变成空数组,传入apply,apply会将数组中的值依次传入,空数组会传undefined,和不传params一样,会赋值undefined,和new一样。