类的继承
function Animal () {
this.type = '哺乳类'
}
Animal.prototype.eat = function () {}
function Tiger () {
Animal.call(this) // 继承Animal私有属性和方法
}
// 继承Animal公有属性和方法的方式一
Object.setPrototypeOf(Tiger.prototype, Animal.prototype)
let tiger = new Tiger()
// 继承Animal公有属性和方法的方式二
Tiger.prototype = Object.create(Animal.prototype, {constructor: {value: Tiger}})
let tiger = new Tiger()
class Animal {
constructor (type) {
this.type = type
}
eat () {
console.log('eat')
}
static flag = 'animal'
static fn () {
return 'fn'
}
}
class Tiger extends Animal {
constructor (type) {
super(type)
}
static fn () {
return super.fn()
}
eat () {
super.eat()
}
}
let tiger = new Tiger('哺乳类')
tiger.eat()
console.log(Tiger.flag)
ES6中的语法
class Animal {
constructor (type) {
this.type = type
}
a = 1 // es7语法
eat () {
console.log('eat', this)
}
get a() { return 100 }
set a() {}
static say () {console.log('say')}
static get a () {return 'hello'}
static n = 200
}
let animal = new Animal('哺乳类')
let eat = animal.eat
eat()
class创建的类和普通函数创建的类的区别:class创建的类不能作为普通函数执行
class 的底层实现原理
转换前
class Parent {
constructor (a) {
this.filed1 = a
}
filed2 = 2
func1 = function () {}
}
转换后
function _classCallCheck(instance, Constructor) {
// instanceof 检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Parent = function Parent(a) {
_classCallCheck(this, Parent);
this.filed2 = 2;
this.func1 = function () { };
this.filed1 = a;
}
可见class的底层依然是构造函数:
1)调用_classCallCheck方法判断当前函数调用前是否有new关键字
构造函数执行前有new关键字,会在构造函数内部创建一个空对象,将构造函数的prototype指向这个空对象的__prpto__,并将this指向这个空对象。如上,_classCallCheck中:this instanceof Parent,返回true。
若构造函数前面没有new则构造函数的prototype不会出现在this的原型链上,返回false
2)将class内部的变量函数赋值给this
3)执行constructor内部的逻辑
4)return this(构造函数默认在最后帮我们做了这一步)