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

class 的本质是 function。

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

基础用法

类定义

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

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

类声明

class Example {
constructor(a) {
this.a = a;
}
}

注意要点:不可重复声明。

class Example{}
class Example{}
// Uncaught SyntaxError: Identifier 'Example' has already been
// declared let Example = class{}
class Example{}
// Uncaught SyntaxError: Identifier 'Example' has already been
// declared

注意要点

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

类中方法不需要 function 关键字。

方法间不能加分号。

new Example(); //Example is not defined  因为类不会提升
class Example {}

类的主体

属性

prototype

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

Example.prototype={
//methods
}

添加方法

Object.assign(Example.prototype,{
//methods
})

静态属性

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

class Example {
// 新提案 静态属性写在内部的提案
static a = 2;
}
// 目前可行写法
Example.b = 3;
console.log(Example);//class Example {static a=2;}
console.log(Example.a);//2
console.log(Example.b);//3

公共属性

class Example{}
Example.prototype.a = 2;

实例属性

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

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

name 属性

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

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 方法

constructor 方法是类的默认方法,创建类的实例化对象时被调用。

class Example{
constructor(){
console.log('我是constructor');
}
}
new Example(); // 我是constructor

返回对象

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

静态方法

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

原型方法

原型方法可以被实例继承,而静态方法不可以被实例继承,同理,静态属性与原型属性同样的道理。静态属性和方法只能类本身使用及拥有。

class Example {
sum(a, b) {//原型方法
console.log(a + b);
}
static sum2=3;//静态属性
}
let exam = new Example();
exam.sum(1, 2); // 3
console.log(exam.sum2);//undefined
console.log(Example.sum2);//3

实例方法

class Example {
constructor() {
this.sum = (a, b) => {//this指向实例对象
console.log(a + b);
}
}
}

类的实例化

new

class 的实例化必须通过 new 关键字。

class Example {}

let exam1 =new Example(); //必须有new关键字  否则报错

实例化对象

共享原型对象

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);
console.log(exam1._proto_ == exam2._proto_); // true
console.log(Example.prototype);//{constructor: ƒ, sum: ƒ}
console.log(exam1.prototype);//undefined
console.log(exam2.prototype);//undefined
Example.prototype.sub=function(){//在类的原型链上添加方法,实例会继承
return this.a-this.b;
}
console.log(exam1.sub()); // 1
console.log(exam2.sub()); // 2

decorator

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

类修饰

一个参数

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

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

多个参数——嵌套实现

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

实例属性

上面两个例子添加的是静态属性,若要添加实例属性,在类的 prototype 上操作即可。

方法修饰

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

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

修饰器执行顺序

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

class Example { @logMethod(1) @logMthod(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

定义

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;
this.c=3;
}
get a(){
console.log('getter');
return this._a;
}
set a(a){
console.log('setter');
this._a = a;
}
}
let exam1 = new Example1(1,2); // 只输出 setter , 不会调用 getter 方法
console.log(exam1);//{_a: 1, b: 2, c: 3}
console.log(exam1.a); // 1,调用getter方法
console.log(exam1._a); // 1, 可以直接访问

getter 不可单独出现

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

getter 与 setter 必须同级出现

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

通过 extends 实现类的继承。

class Child extends Father { ... }

super

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

class Father {
constructor() {
this.b=3;
}
} class Child extends Father {
constructor(a) {
super();//super必须出现在this之前
this.a = a;
}
}
let test = new Child(1);
console.log(test.a);//1
console.log(test.b);//3 这是从父类继承来的

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

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 作为对象,在普通方法中,指向父类的原型对象,在静态方法中,指向父类

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

注意要点

不可继承常规对象。

综合自习:

class Father {
constructor(){
this.a="父类实例属性";
}
static a="父类静态属性";
static geta(){
console.log("父类静态方法");
}
getb(){
console.log("父类原型方法");
}
}
let fatherTest=new Father();
console.log(fatherTest);//{a: "父类实例属性"}
fatherTest.getb();//父类原型方法
// fatherTest.geta();//在实例上无法调用父类的静态方法
Father.geta();//父类静态方法 只有父类本身可以调用 Father.prototype.sum=function(){
console.log("父类原型链上的方法");
}
fatherTest.sum();//父类原型链上的方法 所以可以理解为在父类内定义的原型方法都相当于在原型链上定义 // 继承
class Child extends Father {
constructor(){
super();
this.b="子类实例的属性";
}
static d="子类静态属性";
static e=super.a;//也可以调用父类的静态属性
static getf(){
console.log("子类的静态方法");
}
getg(){
console.log("子类的原型方法");
}
}
let childTest=new Child();
console.log(childTest);// {a: "父类实例属性", b: "子类实例的属性"}
childTest.getb();//父类原型方法 继承来的方法
childTest.getg();//子类的原型方法 子类自身的原型方法

ES6 Class 类的更多相关文章

  1. React和ES6(二)ES6的类和ES7的property initializer

    React与ES6系列: React与ES6(一)开篇介绍 React和ES6(二)ES6的类和ES7的property initializer React与ES6(三)ES6类和方法绑定 React ...

  2. [js高手之路] es6系列教程 - new.target属性与es5改造es6的类语法

    es5的构造函数前面如果不用new调用,this指向window,对象的属性就得不到值了,所以以前我们都要在构造函数中通过判断this是否使用了new关键字来确保普通的函数调用方式都能让对象复制到属性 ...

  3. ES6入门——类的概念

    1.Class的基本用法 概述 JavaScript语言的传统方式是通过构造函数,定义并生成新对象.这种写法和传统的面向对象语言差异很大,下面是一个例子: function Point(x, y) { ...

  4. JavaScript es6 class类的理解。

    本着互联网的分享精神,在本篇文章我将会把我对JavaScript  es6 class类的理解分享给大家. JavaScript 类主要是 JavaScript 现有的基于原型的继承的语法糖. 类语法 ...

  5. ES6 | class类的基本语法总结

    类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式.只要你的代码写在类或模块之中,就只有严格模式可用. 考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 实际上 ...

  6. es6 --- class 类的继承使用

    传统的javascript中只有对象,没有类的概念.它是基于原型的面向对象语言.原型对象特点就是将自身的属性共享给新对象.这样的写法相对于其它传统面向对象语言来讲,很有一种独树一帜的感脚!非常容易让人 ...

  7. ES6 class类中定义私有变量

    ES6 class类中定义私有变量 class类的不足 看起来, es6 中 class 的出现拉近了 JS 和传统 OOP 语言的距离.但是,它仅仅是一个语法糖罢了,不能实现传统 OOP 语言一样的 ...

  8. es6 的类 class

    1.ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类. 2. //定义类 class Point { constructor(x, y ...

  9. ES6——class类继承(读书笔记)

    前言 我一定是一个傻子,昨天这篇文章其实我已经写好了一半了,但是我没有保存 这是学习ES6的过程,我没有系统的看完阮大大的书.零零散散的,很多功能知道,但是没有实际的用过 看了几遍,总是看前面几章,所 ...

  10. ES6 class 类的理解(一)

    优点 ES6 的类提供了几点明显的好处: 兼容当前大量的代码. 相对于构造器和构造器继承,类使初学者更容易入门. 子类化在语言层面支持. 可以子类化内置的构造器. 不再需要继承库:框架之间的代码变得更 ...

随机推荐

  1. Mybatis抛出:Cannot obtain primary key information from the database, generated objects may be incomplete

    使用 mybatis generator 生成pojo.dao.mapper时,可能会遇到 Cannot obtain primary key information from the databas ...

  2. James 如何作为服务在后台启动

    james 启动后是在前台运行的,就像你跑一个微服务,前台运行显然不合理,关闭ssh后就会断开,所以我们得配置在后台,使用service配置即可 配置 james/bin 下的phoenix.sh,配 ...

  3. Atitit 管理的模式扁平化管理 金字塔 直线型管理 垂直管理 水平管理 矩阵式管理 网状式样管理 多头管理 双头管理

    Atitit 管理的模式扁平化管理  金字塔 直线型管理 垂直管理 水平管理 矩阵式管理 网状式样管理 多头管理 双头管理 1.1. 矩阵管理 1 1.2. 相关信息 矩阵的历史 1 1.3. 基于“ ...

  4. 如何保持github的fork于主干同步

    step1: https://help.github.com/articles/configuring-a-remote-for-a-fork/ step2: https://help.github. ...

  5. lua中table的遍历,以及删除

    Lua 内table遍历 在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: 1. ipairs for index, value in ipair ...

  6. tf训练OTSU

    训练一个简单的回归网络 基础的函数如下: # coding=utf-8 import tensorflow as tf import numpy as np np.random.seed(0) # 卷 ...

  7. Windows 10 Manager v2.3.3

    Windows 10 Manager 是专门用于微软 Windows10 的集所有功能于一身的实用工具,它包括了40多个不同的实用程序来优化.调整.清理.加快和修复您的 Windows 10,可以让你 ...

  8. IMAP 读取含有附件邮件超慢问题

    添加以下配置: Properties props = new Properties(); props.setProperty("mail.imap.partialfetch", & ...

  9. linux下启动和关闭tomcat服务的方式

    Linux下tomcat服务的启动.关闭与错误跟踪,通常通过以下几种方式启动关闭tomcat服务: 切换到tomcat主目录下的bin目录 启动tomcat服务 生产模式: 方式一:直接启动 ./st ...

  10. 简化实现动态行列转置的SQL

    动态行列转换的计算在实际业务中非经常见,网上各类技术论坛上都有讨论,比方以下这些问题: http://www.iteye.com/problems/87788 http://bbs.csdn.net/ ...