学习 es6中的类
- 1.了解构造函数的属性
- 2.类的继承
- 2.1继承父类实例上的属性
- 2.2继承父类原型上的属性或则方法(公共属性或则方法)
- 2.2.1 Object.create
- 2.2.2 Object.setPrototypeOf
- 3.es6中的类
- 3.1定义
- 3.2 继承
1.了解构造函数的属性
先上一份代码思考一下它的结果,
function Animal(name) {
//属性分为两种 实例上的属性 公有属性
this.name = name;
this.arr = [1,2,3]
}
Animal.prototype.address = {location: '山间'}
let a1 = new Animal('猴子')
let a2 = new Animal('小鸡')
console.log(a1.arr === a2.arr)
console.log(a1.address === a2.address)
结果是false,true;为什么呢
a1和a2相当于是从Animal拷贝了一份包含name,arr等的数据,明显他俩不是一个内存空间()的,所以他俩的arr肯定是不等的;但是a1和a2都是有一个__proto__属性的,他俩的__proto__刚好指向的就是Animal的prototype,所以他俩的address是一块相同的内存空间,所以是相等的
//每个实例都有一个__proto__指向所属类的原型
console.log(a1.__proto__ === Animal.prototype) //当然这个的结果也是true的
当然a1的constructor就是Animal了
console.log(a1.constructor === Animal) //true
2.类的继承
先创建两个类
function Animal(name) {
this.name = name;
this.arr = [1,2,3]
}
Animal.prototype.address = {location: '山间'}
function Tiger(name) {
this.name = name;
this.age = 10;
}
Tiger.prototype.say = function(){
console.log('说话')
}
2.1继承父类实例上的属性
function Tiger(name) {
this.name = name;
this.age = 10;
Animal.call(this)
}
Tiger.prototype.say = function(){
console.log('说话')
}
let tiger = new Tiger()
console.log(tiger.arr) //[1,2,3]
一般都是不叫私有属性的,因为js来说,基本没有拿不到的属性,不算私有。
2.2继承父类原型上的属性或则方法(公共属性或则方法)
我们是不能直接把tiger的实例直接指向Animal的原型的,应该是先指向自己的tiger原型,如果原型上找不到的话,才去指向Animal的原型
Tiger.prototype.__proto__ = Animal.prototype;
let tiger2 = new Tiger()
console.log(tiger2.address) //{ location: '山间' }
2.2.1 Object.create
其实还可以用es5的object.create()来实现
Tiger.prototype = Object.create(Animal.prototype);
也可以自己写写Object.create的实现原理
function create(parentPrototype) {
let Fn = function () {}
Fn.prototype = parentPrototype;
return new Fn()
}
Tiger.prototype = create(Animal.prototype);
这里有点小饶的,原本是tiger的实例__proto__指向Animal的原型(prototype),现在是tiger的实例指向了Fn的实例(new Fn()),Fn的prototype指向的Animal的prototype。
但是这样写又会有个问题的,如果我们现在打印tiger2的constructor,会是谁呢???
console.log(tiger2.constructor)//[Function: Animal]
会发现是Animal的构造函数,原生的Object.create也是这个结果的,那如果要tiger2的constrctor是Tiger呢,那该怎么写呢,有两种方法:
//1.自定义的create改造下
function create(parentPrototype) {
let Fn = function () {}
Fn.prototype = parentPrototype;
let fn = new Fn();
fn.constructor = Tiger;
return fn
}
//2.Object.create方法加参数配置
Tiger.prototype = Object.create(Animal.prototype,{constructor:{value:Tiger}});
这两种方法是都可以把iger2的constrctor改为Tiger的。
2.2.2 Object.setPrototypeOf
其实还有种es6的写法也可以,还更简洁
Object.setPrototypeOf(Tiger.prototype,Animal.prototype)
一样的效果的,小小的总结下,要继承父类的实例上的属性和公共属性,一般就call+Object.create或则call+Object.setPrototypeOf来实现。
3.es6中的类
3.1定义
class Animal{
static flag(){
return 222
} //es7支持静态属性 es6只支持静态方法
constructor(name){
this.name = name;
this.arr = [1,2,3]
}
//公共的属性方法怎么写呢
//公共的方法
say(){
console.log('say')
console.log(this)
}
}
// 1)类不能当作函数调用
//Animal() //TypeError: Class constructor Animal cannot be invoked without 'new'
let animal = new Animal()
animal.say()
console.log(Animal.flag())
//有个错误的写法
let say = animal.say
say()
//这样看着是没有问题的,我先拿到animal的say方法,再在适合的地方调用它,但是!!!如果方法里有this
//es6规范里 如果单独调用原型上的方法 this是不存在的
// say
// Animal { name: undefined, arr: [ 1, 2, 3 ] }
// say
// undefined
3.2 继承
class Tiger extends Animal{
constructor(name,age){
super(name);
this.age = age;
}
}
let tiger = new Tiger();
tiger.say()
//如果Tiger里面不写constructor的话
let tiger2 = new Tiger('老虎',12);
tiger2.say()
console.log(Tiger.flag()) //静态属性也是可以被继承的 需要被类调用
//如果要写constructor的话,要注意规范