Class类的使用和背后实现的原理
Posted 还是不会呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Class类的使用和背后实现的原理相关的知识,希望对你有一定的参考价值。
在ES6以前,类的声明都是用function构造函数实现的,自ES6开始,可以使用class关键字来创建对象,但是 class只是构造函数定义类的语法糖,内部本质还是构造函数,原型,原型链这一套东西。
类的基本使用
类的创建方法
class关键字创建一个类,和定义function一样,存在声明式和表达式创建
// 方式一:声明式创建
class Person {}
// 方法二:表达式创建
var Student = class {};
类的构造器
在class创建的类中,传递参数用到了构造器 constructor
,创建实例时会自动调用这个方法。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
创建类的实例
创建类的实例还是通过new
关键字
const person = new Person("fzb", 21);
console.log(person); // Person { name: 'fzb', age: 21 }
constructor
内创建对象过程和构造函数一样:
- 创建一个新的对象
- 将新对象的隐式原型赋值为类的原型(显示原型)
- 修改内部this指向
- 执行
constructor
内的代码 - 返回创建的对象
定义类的方法
实例方法
实例方法是放在类的原型上的
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sleepping() {
console.log(this.name + " 在睡觉~");
}
}
const person = new Person("fzb", 21);
person.sleepping(); // fzb 在睡觉~
console.log(Object.getOwnPropertyDescriptors(Person.prototype));
访问器方法
访问器方法是放在类的原型上的
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
set _age(newAge) {
this.age = newAge;
}
get _age() {
return this.age;
}
}
const person = new Person("fzb", 21);
person._age = 22;
console.log(person._age);
console.log(Object.getOwnPropertyDescriptors(Person.prototype));、
静态方法
静态方法是在类的隐式原型上的,通过静态方法可以通过类名.函数名的方式
调用类的方法。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
static createPerson() {
return new Person("fzb", 21);
}
}
const person = Person.createPerson();
console.log(person);
console.log(Object.getOwnPropertyDescriptors(Person.__proto__));
类的继承
使用extends
关键字,可以继承父类的代码和方法,同时可以对父类内的方法进行重写,使用。
在子类构造器类内使用this
和返回默认对象
之前,必须使用super调用父类构造器!不然会报错
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
eatting() {
console.log(this.name + " 在吃饭~");
}
sleepping() {
console.log(this.name + " 在睡觉~");
}
}
class Student extends Person {
constructor(sno, name, age) {
super(name, age);
this.sno = sno;
}
sleepping() {
super.sleepping();
console.log("----------------------");
}
}
const student = new Student(2021, "fzb", 21);
// 调用父类内的方法,也是可以使用父类内的静态方法的
student.eatting(); // fzb 在吃饭~
// 重新父类的方法,并且通过super关键字复用父类对应代码
student.sleepping();
// fzb 在睡觉~
// ----------------------
类的深度解析
通过babel转换,看语法糖class
内部是如何用原型,原型链实现的。
上方代码经过babel转换后是这样的
"use strict";
function _typeof(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof = function _typeof(obj) {
return obj &&
typeof Symbol === "function" &&
obj.constructor === Symbol &&
obj !== Symbol.prototype
? "symbol"
: typeof obj;
};
}
return _typeof(obj);
}
function _get(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get = Reflect.get;
} else {
_get = function _get(target, property, receiver) {
var base = _superPropBase(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get(target, property, receiver || target);
}
function _superPropBase(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf(object);
if (object === null) break;
}
return object;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
// 和 寄生组合式继承思想一样,创建一个新的,新对象的隐式原型执行父类的原型对象,=
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: { value: subClass, writable: true, configurable: true },
});
// 子类的隐式原型指向父类,实现静态方法继承
if (superClass) _setPrototypeOf(subClass, superClass);
}
// 相当于 o.__proto__ = p 实际为例静态实例继承
function _setPrototypeOf(o, p) {
_setPrototypeOf =
Object.setPrototypeOf ||
function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
// Derived:Student子类
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
// 获取Student.__proto__,然而此时的Student.__proto__ = Person
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
// this其实在执行时是子类实例,NewTarget = Student
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
// Super类的实例的__proto__指向NewTarget,并将这个实例返回
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
function _possibleConstructorReturn(self, call) {
if (call && (_typeof(call) === "object" || typeof call === "function")) {
return call;
} else if (call !== void 0) {
throw new TypeError(
"Derived constructors may only return object or undefined"
);
}
return _assertThisInitialized(self);
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError(
"this hasn't been initialised - super() hasn't been called"
);
}
return self;
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Boolean.prototype.valueOf.call(
Reflect.construct(Boolean, [], function () {})
);
return true;
} catch (e) {
return false;
}
}
// 获取对象的o.__proto__
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf
? Object.getPrototypeOf
: function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
// 判断构造函数的调用方式,如果不是通过new调用的方式,就报错
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
// 将props传过来的属性数组,通过描述符加入的 target
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
// 对类里边的方法进行出合理
function _createClass(Constructor, protoProps, staticProps) {
// 实例函数 将实例函数加入到原型对象上
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
// 静态函数加入到对象本身
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
// Person父类,使用了一个自执行函数,clas本质上还是童通过构造函数实现
var Person = /*#__PURE__*/ (function () {
function Person(name, age) {
_classCallCheck(this, Person);
this.name = name;
this.age = age;
}
// 处理内中的方法
_createClass(Person, [
{
key: "eatting",
value: function eatting() {
console.log(this.name + " 在吃饭~");
},
},
{
key: "sleepping",
value: function sleepping() {
console.log(this.name + " 在睡觉~");
},
},
]);
return Person;
})();
// Student子类,使用了一个自执行函数
var Student = /*#__PURE__*/ (function (_Person) {
_inherits(Student, _Person);
var _super = _createSuper(Student);
function Student(sno, name, age) {
var _this;
_classCallCheck(this, Student);
// 获取返回的创建的实例,实际上这个实例是 Person创建出来的,但是改变的this指向
_this = _super.call(this, name, age);
_this.sno = sno;
return _this;
}
// 处理内中的方法
_createClass(Student, [
{
key: "sleepping",
value: function sleepping() {
_get(_getPrototypeOf(Student.prototype), "sleepping", this).call(this);
console.log("----------------------");
},
},
]);
return Student;
})(Person);
以上是关于Class类的使用和背后实现的原理的主要内容,如果未能解决你的问题,请参考以下文章