本片文章为学习完coderwhy老师JS高级课程所做的学习笔记,请勿转载。
ES6中类的使用和对象的使用
使用构造函数的形式创建类,不易理解
es6新标准使用class关键字来直接定义类
// 类的声明
class Person{
}
// 类的表达式
var foo = class {
}
类的特点
class Person {
}
Person.prototype // {}
Person.prototype.__proto__ // {Object: null prototype}
typeof Person // function
var p = new Person()
p.__proto__ === Person.prototype // true
构造函数constructor:创建对象时给类传递一些参数,也称类的构造方法
当我们通过new操作符,操作一个类时会调用这个类的构造函数constructor
每个类只允许有一个构造函数,如果有多个会抛出异常,不允许函数重载
class Person {
constructor(name, age) {
this.name = name
this.age = age
this._address = "广州市"
}
类的实例方法
constructor中定义的方法会被绑定到原型对象上(本质)
在上面我们定义的属性都是直接放到this上,也就意味着它是放到了创建出来的新对象中;
在前面我们说过对应实例的方法,我们是希望把他放到原型上的,这样可以被多个实例来共享
这个时候我们可以直接在类中定义:
// 普通的实例方法
// 创建出来的对象进行访问
// var p = new Person()
// p.eating()
eating() {
console.log(this.name + " eating~")
}
running() {
console.log(this.name + " running~")
}
类的访问器方法
对象可以添加setter/getter函数,类也可以
作用:拦截访问
// 类的访问器方法
get address() {
console.log("拦截访问操作")
return this._address
}
set address(newAddress) {
console.log("拦截设置操作")
this._address = newAddress
}
类的静态方法——static
普通的实例方法是通过创建出来的对象进行访问的,静态方法是通过类名访问的方法,也称类方法
静态方法通常用于定义直接使用类来执行的方法,不需要有类的实例,使用static关键字来定义
// 类的静态方法(类方法)
// Person.createPerson() 调用
static randomPerson() {
var nameIndex = Math.floor(Math.random() * names.length)
var name = names[nameIndex]
var age = Math.floor(Math.random() * 100)
return new Person(name, age)
}
}
es6类的继承——extends
super关键字:子类(派生类)->使用位置:子类的构造函数,实例方法,静态方法
js引擎在解析子类时就有要求,如实现继承,在子类的构造方法中,使用this之前,必须调用super()
即在子类的构造函数中使用this或者返回默认对象之前,必须先通过super调用父类的构造函数
继承方法重写(函数):super调用父类方法,super.xxx()逻辑复用
实例方法放在原型上,静态方法放在类(Person)上,不需new创建实例,调用方式不同
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
running() {
console.log(this.name + " running~")
}
eating() {
console.log(this.name + " eating~")
}
personMethod() {
console.log("处理逻辑1")
console.log("处理逻辑2")
console.log("处理逻辑3")
}
static staticMethod() {
console.log("PersonStaticMethod")
}
}
// Student称之为子类(派生类)
class Student extends Person {
// JS引擎在解析子类的时候就有要求, 如果我们有实现继承
// 那么子类的构造方法中, 在使用this之前
constructor(name, age, sno) {
super(name, age)
this.sno = sno
}
studying() {
console.log(this.name + " studying~")
}
// 类对父类的方法的重写
running() {
console.log("student " + this.name + " running")
}
// 重写personMethod方法
personMethod() {
// 复用父类中的处理逻辑
super.personMethod()
console.log("处理逻辑4")
console.log("处理逻辑5")
console.log("处理逻辑6")
}
// 重写静态方法
static staticMethod() {
super.staticMethod()
console.log("StudentStaticMethod")
}
}
var stu = new Student("why", 18, 111)
console.log(stu)
// console.log(Object.getOwnPropertyDescriptors(stu.__proto__))
// console.log(Object.getOwnPropertyDescriptors(stu.__proto__.__proto__))
stu.eating()
stu.running()
stu.personMethod()
Student.staticMethod()
console.log(Object.getOwnPropertyDescriptors(Person))
es6转es5代码
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
eating() {
console.log(this.name + " eating~")
}
}
转换后
// babel转换
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) { // 多做了一些严格的判断
throw new TypeError("Cannot call a class as a function");
}
}
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;
}
// /*#__PURE__*/ 纯函数
// jsx -> babel -> React.createElement(这个函数会被标记为纯函数)
// webpack 压缩 tree-shaking技术:最终生成代码时没有调用这一部分函数,这部分代码会被删除掉,减小压缩后代码包的大小
// 这个函数没副作用
var Person = /*#__PURE__*/ (function () { //立即执行函数
function Person(name, age) {
this.name = name;
this.age = age;
}
_createClass(Person, [
{
key: "eating",
value: function eating() {
console.log(this.name + " eating~");
}
}
]);
return Person; //返回Person -> 由变量var Person接收
})();
es6转es5代码——继承
super函数内部的核心代码
// Super: Person
// arguments: ["why", 18]
// NewTarget: Student
// 这个方法的目的:会通过Super创建出来一个实例, 但是这个实例的原型constructor指向的是NewTarget
// 会通过Person创建出来一个实例, 但是这个实例的原型constructor指向的Person
Reflect.construct(Super, arguments, NewTarget);