最近在看vue的源码,其中有一部分牵扯到了继承,看到es5中静态方法的"继承"是这样写的vue
const Sub = function VueComponent (options) {
this._init(options)
}
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
...
Sub.extend = Super.extend
Sub.mixin = Super.mixin
Sub.use = Super.use
复制代码
es5的继承你们都知道(经过原型链实现原型属性的继承,经过构造函数实现实例属性的继承),但代码中静态方法是直接从父类赋给子类的,这就想到的一个问题?静态方法没有继承吗?带着这个问题研究了一下静态方法在es5继承中和es6继承中的差别es6
// 定义父类
function Super(name, age) {
this.name = name;
this.age = age;
};
Super.prototype.sayName = function() {
return this.name;
};
// 定义属性
Super.num = 1;
// 定义静态方法
Super.sayWord = function(word) {
return word;
};
// 定义子类
function Sub(name, age, sex) {
// 继承实例属性
Super.call(this, name, age);
this.sex = sex;
}
// 继承父类的原型方法+原型属性
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
var instance = new Sub('张三', '18', '男');
复制代码
分别打印出来看下结果:函数
console.log(Super.sayWord('hello world'));
// print TypeError: Sub.sayWord is not a function
console.log(Sub.sayWord('hello world'));
// print TypeError: Sub.sayWord is not a function
console.log(instance.sayWord('hello world')); // 实例是没法获取到静态方法的
// print instance.sayWord is not a function
复制代码
静态属性和静态方法相似,你们能够自行验证,经过上面的咱们能够得出下面的结论: es5的类继承:子类是没法继承父类的静态属性和静态方法的,只是经过传递测试
其中有个须要注意的地方:静态方法没办法获取到this,因为JavaScript中的类也是一个对象,静态方法至关因而这个类对象的一个属性方法,可是this指的是当前实例对象而不是类对象,因此是没法取到的,下面看下es6中的ui
class Super {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
return this.name;
}
static sayWord(word) {
return word;
}
static get num() {
return this._num; // 由于类也是一个对象 因此_num 只是这个类上的属性 并不是实例属性
}
static set num(n) {
this._num = n;
}
}
class Sub extends Super {
constructor(name, age, sex) {
super(name, age);
this.sex = sex;
}
}
const instance = new Sub('张三', '18', '男');
复制代码
下面咱们分别看下静态方法和静态属性this
console.log(Super.sayWord('hello world'));
// print hello world
console.log(Sub.sayWord('hello world'));
// print hello world
console.log(instance.sayWord('hello world'));
// print TypeError: instance.sayWord is not a function
复制代码
能够看出es6继承中,静态方法被继承下来,这点与es5仍是有差别的,再看静态属性, es6中的静态属性能够直接[类名].[属性名]这样的定义,也能够如上面那样定义(get,set),只是get,set这样的定义咱们能够更好进行的控制es5
Super.num = 3;
console.log(Super.num);
// print 3
console.log(Sub.num);
// print 3
复制代码
看的出,静态属性也被继承了,可是这样也有问题,当静态属性是引用类型时,子类和父类指向的同一个地址,父类若是发生变化子类也会跟着变化,这是咱们不但愿看到的spa
Super.num = [];
Sub.num.push(1);
console.log(Super.num);
// print [1]
console.log(Sub.num);
// print [1]
Super.num.push(2);
console.log(Super.num);
// print [1,2]
console.log(Sub.num);
// print [1,2]
复制代码
咱们修改下静态属性num的get方法,使其只获取本身当前类的值,而非继承的值prototype
static get num() {
return this.hasOwnProperty('_num') ? this._num : undefined;
}
复制代码
再测试一下:code
Super.num = [];
// Sub.num.push(1);
// print TypeError: Cannot read property 'push' of undefined 由于Sub.num获得的是 undefined
Sub.num=1;
console.log(Super.num);
// print []
console.log(Sub.num);
// print 1
Super.num.push(2);
console.log(Super.num);
// print [2]
console.log(Sub.num);
// print 1
复制代码
能够得出:es6中的静态方法和静态属性均可以被继承下来的,只是静态属性的继承须要稍做处理,不然就被共享了
下面咱们再总结下: