class 的特点
- class 不能提升
- class 只能通过 new 实例
- class 采用的严格模式
- class的原型属性不能被遍历
class 例子
es6使用例子
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
say() {
console.log('hello')
}
sayHi() {
console.log('hi')
}
static cat() {
console.log('eat')
}
}
使用es5 模拟一个类
function Person(name, age) {
// 特点3、使用严格模式
'use strict'
// check方法如下,用于检查是否通过 new 方式进行
check();
this.name = name;
this.age = age;
}
检查是否通过 new 的方式进行
function check(instance, constructor) {
// 特点2、class 只能通过 new 实例
if(typeof new target === undefined){
throw new Error('不是通过new执行')
}
}
模拟一个class属性,如上面的例子中, 可以如下表示:
createClass(
Person,
// 实例props
[
{
key: "say",
value: function() {
console.log('hello')
}
},
{
key: "sayHi",
value: function() {
console.log('hi')
}
}
],
// 静态props
[
{
key: "cat",
value: function() {
console.log('cat')
}
}
]
)
由上面描写这个createClass
//
function createClass(constructor, props, staticProps) {
function defineProps(target, props) {
props.forEach(prop => {
// 特点4、不能被遍历
prop.enumerable = prop.enumerable || false;
// 可以被删除
prop.configurable = prop.configurable || true;
// 通过Object.definedProperty实现
Object.definedProperty(target, prop.key, prop);
})
}
// 实例方法
if(props && props.length) defineProps(constructor.prototype, props);
// 静态方法
if(staticProps && staticProps.length) defineProps(constructor, staticProps);
}
本质上来说,静态方法是给class本身赋值,实例方法相当于给实例赋值,实例就是Person.prototype
实现extends
假设有父类Animal,我们看看有些extends干了些啥,Person会继承Animal静态方法、属性、实例方法属性
function _extends(constructor, parentConstructor) {
function extendStatics() {
// 兼容老版本浏览器, 支持__proto__直接返回
if({__prop__: []} instanceof Array){
constructor.__proto__ = parentConstructor
return
}
for(var key in parentConstructor){
// 如果constructor 不包含parentConstructor 的属性,就增加parentConstructor的属性在如果constructor上
if(!(constructor.hasOwnProprety(key))){
constructor[key] = parentConstructor[key]
}
}
}
// 继承静态属性和方法
extendStatics();
// 新的构造函数,将 constructor 只向
function _newConstructor() {
this.constructor = constructor;
}
// 如果父类是null, 则相当于创建一个新的对象
if(parentConstructor === null) {
constructor.prototype = Object.create(null);
}else {
// 否则,通过原型继承 _newConstructor.prototype 指向parentConstructor
_newConstructor.prototype === parentConstructor.prototype;
new _newConstructor();
}
}
// exmpale _extends(Person, Animal)
总结
重写class源码后,有点茅塞顿开的感觉