[ES6] class

news/2024/7/11 1:57:51 标签: es6, javascript

[ES6] class

  • class 类声明
  • class 类定义
  • 属性
    • prototype
      • 添加方法
    • 静态属性
    • 公共属性
    • 实例属性
    • name 属性
  • 方法
    • 构造函数
    • 返回对象
    • 静态方法
    • 原型方法
    • 实例方法
  • 类的实例化
    • 实例化对象
  • decorator
    • 类修饰
    • 方法修饰
    • 修饰器执行顺序
  • 封装与继承
    • getter / setter
    • 继承
    • super
    • 示例

用于定义类似对象之间的共享结构和行为的模板与蓝图

在 ES6 中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类

class 的本质是 function

它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法

class 类声明

es6">class Example {
  constructor(a) {
    this.a = a;
  }
}
es6">class Example {}
class Example {}
// Uncaught SyntaxError: Identifier 'Example' has already been declared

注意,不可重复声明

类定义不会被提升,这意味着,必须在访问前对类进行定义,否则就会报错

类中方法不需要 function 关键字

方法间不能加分号

class 类定义

类表达式可以为匿名或命名

es6">// 匿名类
let Example = class {
  constructor(a) {
    this.a = a;
  }
};
// 命名类
let Example = class Example {
  constructor(a) {
    this.a = a;
  }
};

属性

prototype

ES6 中,prototype 仍存在,虽然可以直接自类中定义方法,但是其实方法还是定义在 prototype 上的。 覆盖方法 / 初始化时添加方法

es6">Example.prototype = {
  //methods
};

添加方法

es6">Object.assign(Example.prototype, {
  //methods
});

静态属性

Class 本身的属性,即直接定义在类内部的属性(Class.propname),不需要实例化。 ES6 中规定,Class 内部只有静态方法,没有静态属性。

es6">class Example {
  // 新提案
  static a = 2;
}
// 目前可行写法
Example.b = 2;

公共属性

es6">class Example {}
Example.prototype.a = 2;

实例属性

定义在实例对象(this)上的属性

es6">class Example {
  a = 2;
  constructor() {
    console.log(this.a);
  }
}

name 属性

返回跟在 class 后的类名(存在时)

es6">let Example = class Exam {
  constructor(a) {
    this.a = a;
  }
};
console.log(Example.name); // Exam

let Example = class {
  constructor(a) {
    this.a = a;
  }
};
console.log(Example.name); // Example

方法

构造函数

类一定包含构造函数–constructor 方法,是类的默认方法,创建类的实例化对象时被调用,实例化的时候会执行构造函数

es6">class Example {
  constructor() {
    console.log("我是 constructor");
  }
}
new Example(); // 我是 constructor

返回对象

es6">class Test {
  constructor() {
    // 默认返回实例对象 this
  }
}
console.log(new Test() instanceof Test); // true

class Example {
  constructor() {
    // 指定返回对象
    return new Test();
  }
}
console.log(new Example() instanceof Example); // false
console.log(new Example() instanceof Test); // true

静态方法

es6">class Example {
  static sum(a, b) {
    console.log(a + b);
  }
}
Example.sum(1, 2); // 3

原型方法

es6">class Example {
  sum(a, b) {
    console.log(a + b);
  }
}
let exam = new Example();
exam.sum(1, 2); // 3

实例方法

es6">class Example {
  constructor() {
    this.sum = (a, b) => {
      console.log(a + b);
    };
  }
}

类的实例化

通过 new 关键字创建类的实例

es6">class Example {}

let exam1 = Example();
// Class constructor Example cannot be invoked without 'new'

new 创建实例时都会执行构造函数

实例化对象

es6">class Example {
  constructor(a, b) {
    this.a = a;
    this.b = b;
    console.log("Example");
  }
  sum() {
    return this.a + this.b;
  }
}
let exam1 = new Example(2, 1);
let exam2 = new Example(3, 1);

// __proto__ 已废弃,不建议使用
// console.log(exam1.__proto__ == exam2.__proto__);

console.log(Object.getPrototypeOf(exam1) === Object.getPrototypeOf(exam2)); // true

Object.getPrototypeOf(exam1).sub = function () {
  return this.a - this.b;
};
console.log(Object.getPrototypeOf(exam1)); //{}
console.log(exam1.sub()); // 1
console.log(exam2.sub()); // 2

decorator

类修饰

decorator, 是一个函数,用来修改类的行为,在代码编译时产生作用

一个参数,第一个参数 target,指向类本身

es6">function testable(target) {
  target.isTestable = true;
}
@testable
class Example {}
Example.isTestable; // true

多个参数——嵌套实现

es6">function testable(isTestable) {
  return function (target) {
    target.isTestable = isTestable;
  };
}
@testable(true)
class Example {}
Example.isTestable; // true

上面两个例子添加的是静态属性,被所有类通用的属性,若要添加实例属性-每个类的实例的属性,在类的 prototype 上操作即可

方法修饰

3 个参数:target(类的原型对象)、name(修饰的属性名)、descriptor(该属性的描述对象)

es6">class Example {
  @writable
  sum(a, b) {
    return a + b;
  }
}
function writable(target, name, descriptor) {
  descriptor.writable = false;
  return descriptor; // 必须返回
}

修饰器执行顺序

由外向内进入,由内向外执行。

es6">class Example {
  @logMethod(1)
  @logMethod(2)
  sum(a, b) {
    return a + b;
  }
}
function logMethod(id) {
  console.log("evaluated logMethod" + id);
  return (target, name, desctiptor) => console.log("excuted logMethod " + id);
}
// evaluated logMethod 1
// evaluated logMethod 2
// excuted logMethod 2
// excuted logMethod 1

封装与继承

getter / setter

es6">class Example {
  constructor(a, b) {
    this.a = a; // 实例化时调用 set 方法
    this.b = b;
  }
  get a() {
    console.log("getter");
    return this.a;
  }
  set a(a) {
    console.log("setter");
    this.a = a; // 自身递归调用
  }
}
let exam = new Example(1, 2); // 不断输出 setter ,最终导致 RangeError

class Example1 {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
  get a() {
    console.log("getter");
    return this._a;
  }
  set a(a) {
    console.log("setter");
    this._a = a;
  }
}
// 只输出 setter , 不会调用 getter 方法 递归
let exam1 = new Example1(1, 2);
console.log(exam1._a); // 1, 可以直接访问

getter 不可单独出现

es6">class Example {
  constructor(a) {
    this.a = a;
  }
  get a() {
    return this.a;
  }
}
let exam = new Example(1); // Uncaught TypeError: Cannot set property // a of #<Example> which has only a getter

需要初始化有效的类,所以必须有 set 方法

getter 与 setter 必须同级出现

es6">class Father {
  constructor() {}
  get a() {
    return this._a;
  }
}
class Child extends Father {
  constructor() {
    super();
  }
  set a(a) {
    this._a = a;
  }
}
let test = new Child();
test.a = 2;
console.log(test.a); // undefined

class Father1 {
  constructor() {}
  // 或者都放在子类中
  get a() {
    return this._a;
  }
  set a(a) {
    this._a = a;
  }
}
class Child1 extends Father1 {
  constructor() {
    super();
  }
}
let test1 = new Child1();
test1.a = 2;
console.log(test1.a); // 2

继承

使用 extends 关键字继承父类,并再构造函数中调用 super(param)执行父类的构造函数,通过 extends 实现类的继承

es6">class Child extends Father {}

super

子类 constructor 方法中必须有 super ,且必须出现在 this 之前

es6">class Father {
  constructor() {}
}
class Child extends Father {
  constructor() {}
  // or
  // constructor(a) {
  // this.a = a;
  // super();
  // }
}
let test = new Child(); // Uncaught ReferenceError: Must call super
// constructor in derived class before accessing 'this' or returning
// from derived constructor

调用父类构造函数,只能出现在子类的构造函数

es6">class Father {
  test() {
    return 0;
  }
  static test1() {
    return 1;
  }
}
class Child extends Father {
  constructor() {
    super();
  }
}
class Child1 extends Father {
  test2() {
    super(); // Uncaught SyntaxError: 'super' keyword unexpected
    // here
  }
}

调用父类方法, super 作为对象,在普通方法中,指向父类的原型对象,在静态方法中,指向父类

es6">class Child2 extends Father {
  constructor() {
    super();
    // 调用父类普通方法
    console.log(super.test()); // 0
  }
  static test3() {
    // 调用父类静态方法
    return super.test1 + 2;
  }
}
Child2.test3(); // 3

注意,不可继承常规对象

es6">var Father = {
  // ...
};
class Child extends Father {
  // ...
}
// Uncaught TypeError: Class extends value #<Object> is not a constructor or null

// 解决方案
Object.setPrototypeOf(Child.prototype, Father);

示例

es6">class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Welcome to check ${this.name} resource`);
  }
}

class Author extends Person {
  constructor(name, type) {
    super(name);
    this.type = type;
  }

  greet() {
    console.log(`Welcome to check Author ${this.name} of ${this.type} resource`);
  }
}
const peo = new Person("San mao");
const author1 = new Author("Lun xun", "Novel");
const author2 = new Author("Three", "Army");

peo.greet(); //Welcome to check San mao resource
author1.greet(); //Welcome to check Author Lun xun of Novel resource
author2.greet(); //Welcome to check Author Three of Army resource

http://www.niftyadmin.cn/n/5030173.html

相关文章

python经典百题之寻找完数

题目&#xff1a;一个数如果恰好等于它的因子之和&#xff0c;这个数就称为“完数”。例如61&#xff0b;2&#xff0b;3.编程 找出1000以内的所有完数。 方法一&#xff1a; 思路&#xff1a;利用两个循环分别枚举每个数和它的因子&#xff0c;如果发现一个数的因子之和等于…

Vim的基础操作

前言 本文将向您介绍关于vim的基础操作 基础操作 在讲配置之前&#xff0c;我们可以新建一个文件 .vimrc&#xff0c;并用vim打开在里面输入set nu 先给界面加上行数&#xff0c;然后shift &#xff1b;输入wq退出 默认打开&#xff1a;命令模式 在命令模式中&#xff1a…

mybatis动态sqlchooseforeachsql 及include sql中的特殊字符后台分页实现 数据版本号处理并发问题

1. 动态sql简述 mybatis的动态sql语句是基于OGNL表达式的。可以方便的在sql语句中实现某些逻辑. 总体说来mybatis动态SQL语句主要有以下几类: if 语句 (简单的条件判断)choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似trim (对包含的内容加…

汽车电子软件开发AutoSAR BSW开发分享

前言&#xff1a;计划从本贴之后分享一些AutoSAR BSW开发心得 此贴算是分享更多的是警惕自己&#xff0c;毕竟自从毕业后&#xff08;19年&#xff09;之后帖子就没更新过。 最大的原因还是懒吧&#xff0c;也有许许多多的顾虑在&#xff0c;一方面是刚入门的小菜鸡感觉无甚可…

面相面试知识--Lottery项目

面相面试知识–Lottery项目 1.设计模式 为什么需要设计模式&#xff1f; &#xff08;设计模式是什么&#xff1f;优点有哪些&#xff1f;&#xff09; 设计模式是一套经过验证的有效的软件开发指导思想/解决方案&#xff1b;提高代码的可重用性和可维护性&#xff1b;提高团…

Vue2电商前台项目——完成加入购物车功能和购物车页面

Vue2电商前台项目——完成加入购物车功能和购物车页面 文章目录 Vue2电商前台项目——完成加入购物车功能和购物车页面一、加入购物车1、路由跳转前先发请求把商品数据给服务器&#xff08;1&#xff09;观察接口文档&#xff08;2&#xff09;写接口&#xff08;3&#xff09;…

用c++实现五子棋小游戏

五子棋是一款经典小游戏&#xff0c;今天我们就用c实现简单的五子棋小游戏 目录 用到的算法&#xff1a; 思路分析 定义变量 开始写代码 完整代码 结果图&#xff1a; 用到的算法&#xff1a; 合法移动的判断&#xff1a;isValidMove 函数通过检查指定位置是否在棋盘范…

谈谈前端的本地存储indexedDB

前言 想必前端本得资源化在我们日常工作中也是经常用的一个技术了&#xff0c;其中我们常用的莫过于cookie、Web Storage&#xff08;sessionStorage、localStorage&#xff09;&#xff0c;但这些本地化存储方式比较明显的缺陷&#xff0c;例如&#xff1a; 1.cookie&#x…