es6(五)—— class(类)详解

这篇具有很好参考价值的文章主要介绍了es6(五)—— class(类)详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一:构造函数

在了解class (类)的使用之前,需要先了解一下什么是构造函数

1:定义:通常首字母大写,用于和普通函数区分(不大写也可以,但是前端为了更好区分使用大写)。
2:区别:构造函数和普通函数的区别就是调用方式的不同,普通函数是直接调用,而构造函数需要使用new关键字来调用。
3、执行流程

  1. 立即创建一个新的对象
  2. 将新建的对象赋值给函数中的this
  3. 从上至下依次执行函数中的代码
  4. 将新建的对象作为返回值返回

4:返回值:默认是返回this,也就是new 出来的实例对象,如果有返回值就根据返回值来
5:作用:新建实例对象,并且给实例对象内的成员(属性或方法)进行赋值:。

function Person(name){
  console.log('我是'+ name);
 }
 let p = new Person('张三');
 console.log('p', p);

打印如下
es6 class,es6,es6,javascript,前端

二:类(class)

0:类里面为什么要使用构造函数?
class Person{
 // 每new一个对象后都会执行这个函数
  constructor(name, age, gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
  }
}
console.log(typeof Person); // function

// 不使用构造函数
let p0 = new Person();
p0.name= '张三';
p0.age= 18;
p0.gender= '男';
console.log(typeof p0); // object

// 使用构造函数
let p1 = new Person('李四', 19, '男');
console.log(typeof p1); // object

let p2 = new Person('王五', 20, '女');
console.log(typeof p2); // object

// 综上:class中使用构造函数的作用就是减少了代码的赋值。

综上:class中使用构造函数的作用就是减少了代码的赋值。

1:类的由来

JavaScript 语言中,生成实例对象的传统方法是通过构造函数。新的class写法是为了让对象原型的写法更加清晰,更新面向编程的写法。

// 构造函数生成实例对象(传统方法)
function Person(x, y){
  this.x = x;
   this.y = y;
 }
 Person.prototype.toString = function () {
   return '(' + this.x + ', ' + this.y + ')';
 };
 var p = new Person(1, 2);

 // class 关键字创建的实例对象(es6)
 class Person{
   constructor(x, y){
     this.x = x;
     this.y = y;
   }
   toString() {
     return '(' + this.x + ', ' + this.y + ')';
   }
 };
2:类的constructor函数

(1)constructor()方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。

// 如下两行代码的效果其实是一样的
class Person{}  
class Person{ constructor() }

(2)值得注意的是:类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。

class Person{ // ... }
var person= Person('张三', 18); // 报错
var person = new Person('李四', 19); // 正确
3:类的实例(__ proto __)

类的所有实例共享一个原型对象

var p1= new Person('张三', 18);
var p2= new Person('李四', 19);
p1.__proto__ === p2.__proto__  // true

上诉代码的p1和p2都是person的实例,原型都是person.prototype,因此__proto__也是相等的。这说明,你可以通过实例__proto__属性为类添加方法。

注意1:__proto__是厂商添加的私有属性,即使有很多浏览器都提供 了这个属性,但是仍然不推荐你使用在生成环境中。生成环境中可以使用 Object.getPrototypeOf() 方法来获取实例对象的原型,然后再来为原型添加方法/属性。
注意2:__proto__上添加属性,这会改变类的原始定义,因而使用必须谨慎。

4:类的原型(prototype)

类的所有方法都定义在类的prototype属性上面。

class Person{
  constructor() {
    // ...
  }
  toString() {
    // ...
  }
  toValue() {
    // ...
  }
}

// 等同于

Person.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};

也就是说:在类的实例上面调用方法,其实就是调用原型上的方法(如下代码)

class B {}
const b = new B();

b.constructor === B.prototype.constructor // true

prototype对象的constructor属性,直接指向“类”的本身,这与 ES5 的行为是一致的。
注意:toString()方法是Person类内部定义的方法,它是不可枚举的。另外,类的内部所有定义的方法,都是不可枚举的。

5:类的取值函数(getter)和存值函数(setter)

作用:为了能够在类中拦截该属性的存取行为

class MyClass {
   constructor(name, age) {
       this.name = name;
       this.age = age;
   }
   get prop() {
       return 'getter';
   }
   set prop(value) {
       console.log('setter: '+value);
   }
}
let p = new MyClass('张三', 18);
p.prop = 123;  // setter: 123

存值函数和取值函数是设置在属性的 Descriptor 对象上的。

class CustomHTMLElement {
  constructor(element) {
    this.element = element;
  }
  get html() {
    return this.element.innerHTML;
  }
  set html(value) {
    this.element.innerHTML = value;
  }
}

var descriptor = Object.getOwnPropertyDescriptor(
  CustomHTMLElement.prototype, "html"
);
"get" in descriptor  // true
"set" in descriptor  // true
6:类的表达式

1:使用语法

(1)class Person {} // 类的定义
(2)const MyClass = class Me {} // 类的表达式

2:定义
假设在const MyClass = class Me {} 代码中
(1)在Class内部,这个类的名字是Me,Me只在Class 的内部可用
(2)在Class外部,这个类只能用MyClass引用。

const MyClass = class Me {
  getClassName() {
    return Me.name;
  }
};
let my= new MyClass();
my.getClassName() // Me
Me.name // ReferenceError: Me is not defined

(3)区别
函数声明会提升,类声明不会。需要先声明类,然后再访问它,否则就会出现ReferenceError

// Person is not defined
const test = new Person(); 
class Person {}

// undefined
class Person {}  
const test = new Person(); 
7:类的属性表达式

这没啥好说的,就是通过定义变量,然后在类里面通过[]的方式来获取变量,即Person的方法名getName,是从表达式得到的。

let methodName = 'getName';

class Person{
  constructor(length) {
    // ...
  }
  [methodName]() {
    // ...
  }
}
8:静态属性、静态方法和静态块

静态属性、静态方法和静态块都是通过关键字static来定义的

(1)静态方法

①定义:如果在一个方法前,加上static关键字,这就称为“静态方法”。
②作用:表示该方法不会被实例继承,而是直接通过类来调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。
③注意点:如果静态方法包含this关键字,这个this指的是类,而不是实例。

class Foo {
  static bar() {
    this.baz();
  }
  static baz() {
    console.log('hello');
  }
  baz() {
    console.log('world');
  }
}

Foo.bar() // hello

上面代码中,静态方法bar调用了this.baz,这里的this指的是Foo类,而不是Foo的实例,等同于调用Foo.baz。另外,从这个例子还可以看出,静态方法可以与非静态方法重名。
④父类的静态方法,可以被子类继承。
⑤静态方法也是可以从super对象上调用的。

(2)静态属性

①定义:静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性。
②新老写法的对比
老写法:定义在类的外部,整个类生成以后再生成静态属性。容易忽略。
新写法:显式声明,语义更好。

// 老写法
class Person{
  // ...
}
Person.personName= "张三";

// 新写法
class Person{
  static personName= "张三";
}
(3)静态块

①由来:如果有初始化逻辑,这个逻辑要么写在类的外部,要么写在constructor()方法里面。前者是将类的内部逻辑写到了外部,后者则是每次新建实例都会运行一次。ES2022 引入了静态块(static block),允许在类的内部设置一个代码块,在类生成时运行且只运行一次,主要作用是对静态属性进行初始化。以后,新建类的实例时,这个块就不运行了。
②作用:为了解决初始化逻辑存放位置的问题。
③使用:每个类允许有多个静态块,每个静态块中只能访问之前声明的静态属性。另外,静态块的内部不能有return语句。静态块内部可以使用类名或this,指代当前类。除了静态属性的初始化,静态块还有一个作用,就是将私有属性与类的外部代码分享。

let getNme;

export class C {
  // 每个类允许有多个静态块,每个静态块中只能访问之前声明的静态属性
  static personName= "张三";
  static {
    this.personName; // 张三
    // 或者
    C.personName; // 张三
  }
  #personName= "张三";
  static {
    getX = obj => obj.#personName;
  }
}
console.log(getX(new C())); // 张三

上面示例中,#x是类的私有属性,如果类外部的getX()方法希望获取这个属性,以前是要写在类的constructor()方法里面,这样的话,每次新建实例都会定义一次getX()方法。现在可以写在静态块里面,这样的话,只在类生成时定义一次。

9:私有方法和私有属性
(1)老方法

早期私有方法和私有属性通过方法或属性前面添加_来表示这是一个内部使用的私有方法,或者使用Symbol值的唯一性,将私有方法的名字命名为一个Symbol值。

const bar = Symbol('bar');
const snaf = Symbol('snaf');

export default class myClass{

  // 公有方法
  foo(baz) {
    this[bar](baz);
  }

  // 私有方法
  [bar](baz) {
    return this[snaf] = baz;
  }
  // ...
};

上面代码中,bar和snaf都是Symbol值,一般情况下无法获取到它们,因此达到了私有方法和私有属性的效果。但是也不是绝对不行,Reflect.ownKeys()依然可以拿到它们。

const inst = new myClass();
Reflect.ownKeys(myClass.prototype)
// [ 'constructor', 'foo', Symbol(bar) ]
(2)新写法(ES2022)

①定义:ES2022正式为class添加了私有属性,私有属性和私有方法,是只能在类的内部访问的方法和属性,外部不能访问,不可以直接通过 Class 实例来引用。
②使用:在方法或者是属性名之前使用#表示。

class Person{
  #personName= '张三'; // #personName就是私有属性,只能在类的内部使用(this.#personName)。如果在类的外部使用,就会报错。
  get value() {
    console.log('Getting the current value!');
    return this.#personName;
  }
}
const getPersonName= new Person();
gName.#personName// 报错
gName.#personName= 42 // 报错

③注意点:私有方法只能内部调用,在外部调用就会报错。

10:其他
1:类不存在变量提升
2:name属性:name属性总是返回紧跟在class关键字后面的类名。
class Person{}
Person.name // "Person"
3:this指向

问题:类的方法内部如果含有this,它默认指向类的实例。但是如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境(由于 class 内部是严格模式,所以 this 实际指向的是undefined),从而导致找不到方法而报错。
解决方法:在构造方法中绑定this或者使用箭头函数

参考文章:https://es6.ruanyifeng.com/#docs/class文章来源地址https://www.toymoban.com/news/detail-775097.html

到了这里,关于es6(五)—— class(类)详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ES6】class静态方法

    类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。 上面代码中,Foo类的classMethod方法前有static,表明该方法是一个静态方法,可以直

    2024年02月09日
    浏览(32)
  • ES6学习-Class类

    constructor 构造方法 this 代表实例对象 方法之间不需要逗号分隔,加了会报错。 类的数据类型就是函数,类本身就指向构造函数。 类的所有方法都定义在类的 prototype 属性上面 类的内部所有定义的方法,都是不可枚举的(non-enumerable) ES6类内部定义的方法不可枚举;ES5可以

    2024年02月14日
    浏览(33)
  • ES6——class类实现继承

    赶快悄悄的努力起来吧,不苒在这里衷心祝愿各位大佬都能顺利通过面试。 面试专栏分享,感觉有用的小伙伴可以点个订阅,不定时更新相关面试题:面试专栏 。 在ES6 中新增了 extends ,用于实现类的继承。 MDN中对 extends 的解释是这么说的: **定义:**** exten

    2023年04月10日
    浏览(37)
  • 【ES6】Class中this指向

    先上代码: 正常运行的代码: 输出: 单独调用函数printName: 输出: debugger调试一下,看看什么情况,调试代码: 调试界面,this显示undefined,在单独调用时,this的指向是undefined。在单独调用的场景下,要如何才能解决该问题呢?下面给出两种种比较简单的解决方法。 1、在

    2024年02月09日
    浏览(36)
  • ES5 构造函数与ES6 Class的区别

    Class 类中不存在变量提升 class内部会启用严格模式 class的所有方法都是不可枚举的 class 必须使用new调用 class 内部无法重写类名 class 的继承有两条继承链 一条是: 子类的__proto__ 指向父类 另一条: 子类prototype属性的__proto__属性指向父类的prototype属性. es6的子类可以通过__pro

    2024年02月06日
    浏览(106)
  • 【ES6】中构造函数的语法糖 —— Class(类)

            在现代前端开发中,JavaScript的面向对象编程成为了主流。ES6引入了class,使得开发者可以更方便地使用面向对象的方式编写代码,更接近传统语言的写法。ES6的class可以看作是一个语法糖,它的绝大部分功能ES5都可以做到,新的class写法只是让对象原型的写法更

    2024年02月16日
    浏览(33)
  • ES6之浅尝辄止1:class的用法

    class是es6新增的一种语法糖,用于简化js中构造类的过程

    2024年02月11日
    浏览(56)
  • ts的class类的使用与继承, es6新增的class类

    前言:         ts的class类的使用与继承, es6新增的class类。         在ES6中为了更好的把js设计成面向对象的语言的语法特征,提出了class 类,class的本质是函数,类不可重复声明,类定义不会被提升,让js更像面向对象编程的语法。         类名建议大写,在严格要求

    2024年02月05日
    浏览(43)
  • ES6中的Class关键字和super()方法,使用详细(class类和super()方法)

    简介:在ES6中,我们可以使用class来定义类,并通过 extends 实现类的继承,然后在子类中,我们可以使用 super() 来调用父类的构造函数;今天来分享下class的使用详细。 1、 首先,使用class,定义一个父类; 2、 然后再定义一个子类, 通过ex

    2024年02月12日
    浏览(47)
  • ES6之Promise、Class类与模块化(Modules)

    Promise 是 ES6 引入的一种用于 处理异步操作 的对象。 它解决了传统回调函数(callback)模式中容易出现的 回调地狱 和代码可读性差的问题。 Promise 对象有三种状态: Pending (进行中): 初始化状态,表示异步操作还在进行中。 Fulfilled (已成功): 表示异步操作执行成功,并

    2024年02月10日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包