es6及以上的Class

5 篇文章 0 订阅
2 篇文章 0 订阅

简介

作为前端开发人员,并不陌生es5,es6。今天在这里主要是讲讲es6的Class,它具体是干什么的。这篇幅主要是针对,对于es6中Class使用较少,不了解Class的人员进行一个大概的描述,并对Class的一些注意点进行标注。可以方便快捷的了解Class。

Class的定义

Class是一个语法糖,当我们使用Class声明一个变量的时候,就类似于es5中我们使用function 声明一个具名的构造函数.简化来说,就是Class声明的‘类’近似等于构造函数。在class声明的变量中的函数方法,都是直接作用到es5中funtion.prototype上

老规矩,上代码先:

// es5 进行自定义一个构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.toString = function () {
return '名称:' + this.name + '年龄:' + this.age
}
var p = new Person('章三', 20);
// 输出 {name: '章三', age: 20}

// es6的改版
class Person {
  constructor(name, age) {
  this.name = name
  this.age = age
  }
  toString() {
  return '名称:' + this.name + '年龄:' + this.age
  }
}
var p = new Person('李四', 20);
// 输出 {name: '李四', age: 20}

上面的代码只是一个简单的例子,很明显咱们可以看出结构上面有很大的差别,es5之前自定义一个‘类’,就是使用funtion进行声明。如果需要自定义一些其他函数,还需要再使用其原型进行定义。es6的结构,则不需要额外进行再进行声明,具体的情况再往下看。

Class的一些要点

es5 与 es6 在Class上面的异同点

es5于es6的不同点
  1. Class 声明‘类’,在es5 之前都是没有,于es6 开始支持该声明变量的方法,简化了代码,让js代码使java等后端人员更好的认识。
  2. es5 在声明‘类’的时候,直接使用function进行声明一个构造函数,es6及以上版本,则是使用class声明包含构造函数的‘类’
  3. es5 声明的‘类’,在其原型上面添加的函数变量都是可以被枚举的,es6声明的则不可以。
  4. es6 生成的类,必须使用 new 调用,这也是区别去普通构造函数的一点
  5. es6 class 不进行变量提升
  6. 严格模式,es6在class 中严格执行严格模式
es5于es6的相同点
  1. 生成对应的实例,都是使用new进行操作,并且共享同一个原型对象
  2. getter(取值函数)和 setter(存值函数)仍然存在于Descriptor对象上

Class上容易忽视的点

  1. 方法之间不需要逗号‘,’,可使用分号‘;’。
  2. class声明的变量 等于 该变量的构造函数 。例: Person=== Person.prototype.constructor
  3. 内部所定义的方法,不可被枚举,因此使用Object.keys()是获取不到自定义(除去constructor构造方法)方法的,使用Object.getOwnPropertyNames()方法可以获取。
  4. 如果一个类没有显式定义constructor方法,会被默认添加一个constructor 方法
  5. 类的属性名,可以使用表达式
let message = 'getName'
class Person {
_name = '章三';
  [message]() {
  return this._name
  }
}
const people = new Person()
console.log(people[message]()) // 章三
  1. 类也是可以使用表达式进行表示
// 这个例子中的Person 类,只能在Woman里面使用,如果执行new Person() 就会报错
const Woman = class Person {
getNames() {
 return Person.name
}
const woman = new Woman()
woman.getNames() // Person 
}
const Man = class {}
// 以上两种是表达式进行表示类,不同的是,第一种,能找到对应的类的名称,并且很明显,知道原始类是谁。
  1. 静态方法是不能被 实例 继承的,只能被类所使用(子类进行继承 extends) 。并且静态方法中的this指的是类,而不是实例
class Person{
  name = '章三';
  static getName() {
    return this.name
  }
  getName() {
    return this.name
  }
}
class Man extends Person{}
const man = new Person()
console.log(man.getName()) // 章三
console.log(Person.getName()) // Person
console.log(Man.getName()) // Man
  1. 静态属性
calss Foo {}
Foo.prop = 1;
// 2022 新写法
class Foo {
  static prop = 1;
}
  1. 私有属性和私有方法是无法被实例所使用的,只能是类本身使用

Class 的新要点

  1. 实例属性的改变。上代码:这种写法是定义 实例对象 自身的属性,并非实力对象原型的属性
// ES2022之前版本
class IncreasingCounter {
  constructor() {
  this._count = 0
  }
  increment() {
    this._count++;
  }
}
// ES2022的新版本
class IncreasingCounter {
  _count = 0;
  increment() {
    this._count++;
  }
}
const a = new IncreasingCounter()
a.increment()
console.log(a._count)  // 1
  1. 私有属性于私有方法(2022开始施行),2022之前没有真正的私有属性和私有方法(之前的定义方法只是在使用上的区别,但也还是能得到并且使用的,出现symbol这种类型的时候,虽然能解决,但未完全解决,仍然可以使用Reflect.ownKeys()获得)
// 私有属性发展史
// 1. 刚开始在定义类的时候,使用下划线开头的定为私有方法和私有属性
// 2. symbol的唯一性,将私有方法的名称唯一化
const symbol = Symbol('symbol')
class Symbolfun = {
	[symbol](text) {
		this[text] = text
	}
}
// 3. 最新的声明方式, #声明的变量是私有属性,static声明的方法是私有方法
class Fun = {
	#text = 1; // 私有属性,初始值,可不赋值
	get #text() { // 私有方法,私有属性的getter方法
		return this.#text
	}
	set #text(text) {
		this.#text = text
	}
}
  1. 无法进行变量提升
// class 只有先定义才能使用,这是因为与继承有关
// 例子1
new Foo() // ReferenceError
class Foo {}

// 例子2 ,如果class可以提升,则继承的时候,let声明的Foo并没有提升,这就会导致Foo没有值,则会导致报错。
let Foo = class {}
const Bar extends Foo {
}
  1. 类自带name,并且name值为类名,且无法修改
class Preson {}
Person.name // Person
  1. Generator 方法(不明白的可以看一下es6的generator方法), 就是在类方法前增加*,表示一个generator方法,具体看下面的例子
class Counter {
    constructor(limit) {
        this.limit = limit;
        this.current = 0;
    }
 
    *incrementToLimit() {
        while (this.current < this.limit) {
            this.current += 1;
            console.log(`Current: ${this.current}`);
            yield;
        }
    }
}
 
const counter = new Counter(5);
const iterator = counter.incrementToLimit();
 
console.log('Starting...');
iterator.next(); // 输出: Starting...
iterator.next(); // 输出: Current: 1
iterator.next(); // 输出: Current: 2
// ...继续执行,直到达到限制值。
  1. this的指向 (类的方法内部如果含有 this ,它默认指向类的实例所运行的环境。如果想要让this指向实例,有两种方案可以使用。所以class中this慎用)
// 第一种方案, 构造函数中,使用bind进行绑定this
class Logger {
constructor() {
    this.printName = this.printName.bind(this);
  }
  printName(name = 'there') {
  // 未增加 构造函数的时候,此时的this指的是实例的所处环境的this
    this.print(`Hello ${name}`);
  }
  print(text) {
    console.log(text);
  }
}
const logger = new Logger();
const { printName } = logger;
printName();
// 第二种方案,还是在构造函数中使用箭头函数接受一下对应的this
class Obj {
  constructor() {
    this.getThis = () => this;
  }
}
const myObj = new Obj();
myObj.getThis() === myObj // true
  1. 静态方法与静态属性(类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上 static 关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法“。 )(静态属性指的是Class本身的属性,即 Class.propName,而不是定义在实例对象( this )上的属性。提案,静态属性在前面使用static)
// 以下例子,标明了静态方法和静态方法中this的指向
class Foo {
  static bar() {
    this.baz();
  }
  static baz() {
    console.log('hello');
  }
  baz() {
    console.log('world');
  }
}
Foo.bar() // hello

const foo = new Foo()
foo.bar() // TypeError: foo.bar is not a function

// 静态属性的例子, myStaticProp 就是类MyClass的静态属性,只能被类自身使用
class MyClass {
  static myStaticProp = 42;
  constructor() {
    console.log(MyClass.myStaticProp); // 42
  }
}
  1. 私有属性和私有方法 (私有方法,两种方案:类里面命名加_ ,第二种是声明在类外面)(私有属性,提案是在属性名前加 # )
  2. new.target === 类,该属性一般用在构造函数之中。可以用来判断是否通过new进行生成实例,但可以被子类继承,子类继承的时候,new.target就是子类。因此可以形成一个公共类,只能继承的使用方法。例子如下:
class Shape {
  constructor() {
    if (new.target === Shape) {
      throw new Error('本类不能实例化');
    }
  }
}
class Rectangle extends Shape {
  constructor(length, width) {
    super();
    // ...
  }
}
var x = new Shape();  // 报错
var y = new Rectangle(3, 4);  // 正确

总结

es6及以上对于类还是一直在封装发展,所以,现在这些东西或许后面还会进行改变。不过也需要我们了解class的演变,懂的底层越多,后面成长性会越高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值