ES5 的构造函数和 ES6 的类有什么区别

这篇具有很好参考价值的文章主要介绍了ES5 的构造函数和 ES6 的类有什么区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


在JavaScript中,类和构造函数都被用来创建对象,接下来会从以下几点说说两者的区别:

语法不同

  • 构造函数使用函数来定义
  • 类使用class关键字来定义

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

比如这是一个构造函数生成实例对象的例子,

function Point(x, y) {
  this.x = x;
  this.y = y;
}
Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
console.log(p.toString()) // (1, 2)

上面的代码用类来改写是这样的,

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
var p = new Point(1, 2);
console.log(p.toString()) // (1, 2)

所以类完全可以看作构造函数的另一种写法,

class Point {
  // ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true

类的数据类型就是函数,类本身就指向构造函数。

方法定义方式不同

  • 构造函数的方法都是定义在构造函数的原型上,即原型上的方法被所有实例共享
  • 类的方法可以直接定义在类中,也可以定义在类的原型上,而且定义在类中的方法是不可枚举的。

构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。

class Point {
  constructor() {
    // ...
  }
  toString() {
    // ...
  }
  toValue() {
    // ...
  }
}
// 等同于
Point.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};

以下代码表明类的内部所有定义的方法,都是不可枚举的(non-enumerable)

class Point {
  constructor(x, y) {
    // ...
  }
  toString() {
    // ...
  }
}
Object.keys(Point.prototype) // []
Object.getOwnPropertyNames(Point.prototype) // ["constructor","toString"]

而直接定义在原型上的都是可枚举的

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
Point.prototype.toString1 = function() {
  // ...
};

console.log(Object.keys(Point.prototype)) // [ 'toString1' ]
console.log(Object.getOwnPropertyNames(Point.prototype)) // [ 'constructor', 'toString', 'toString1' ]

继承方式不同

  • 构造函数通过将一个构造函数作为另一个构造函数的原型,实现原型链继承,可以实现单继承和多继承。
  • 类通过extends关键字来实现继承,支持单继承,子类继承父类的属性和方法,可以调用父类的构造函数。

构造函数的继承需要手动处理原型链,并确保构造函数和原型的正确指向,以下示例可看出

function Animal(name) {
  this.name = name;
}

Animal.prototype.eat = function() {
  console.log(this.name + ' is eating.');
};

function Dog(name, breed) {
  Animal.call(this, name); // 调用父类构造函数
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype); // 设置子类的原型对象
Dog.prototype.constructor = Dog; // 重设构造函数指向自身

Dog.prototype.bark = function() {
  console.log(this.name + ' is barking.');
};

const dog = new Dog('Buddy', 'Golden Retriever');
dog.eat(); // 输出: Buddy is eating.
dog.bark(); // 输出: Buddy is barking.

类的继承示例

class Animal {
  constructor(name) {
    this.name = name;
  }
  eat() {
    console.log(`${this.name} is eating.`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 调用父类构造函数
    this.breed = breed;
  }
  bark() {
    console.log(`${this.name} is barking.`);
  }
}

const dog = new Dog('Buddy', 'Golden Retriever');
dog.eat(); // Buddy is eating.
dog.bark(); // Buddy is barking.

需要注意的是,子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
如果子类没有定义constructor方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有constructor方法。

class Dog extends Animal {
}
// 等同于
class Dog extends Animal {
  constructor(...args) {
    super(...args);
  }
}

另一个需要注意的地方是,在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。

class Animal {
  constructor(name) {
    this.name = name;
  }
}
class Cat extends Animal {
  constructor(name, color) {
    this.color = color; // ReferenceError
    super(name);
    this.color = color; // 正确
  }
}

类内部的this指向不同

  • ES5中,类内部函数中的this指向调用函数的对象
  • ES6中,类内部方法中的this指向实例对象
    注意:如果静态方法中包含this关键字,这个this指的是类,而不是实例。
class Foo {
  static classMethod() {
    return 'hello';
  }}

Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function

静态成员定义方式不同

  • ES5中,静态成员需要通过给构造函数手动添加属性或方法来实现
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.staticMethod = function() {
  console.log("This is a static method.");
};
  • ES6中,可以使用static关键字定义静态属性或方法
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  static staticMethod() {
    console.log("This is a static method.");
  }
}

访问器属性

  • ES6中引入了getter和setter方法,可以使用get和set关键字定义访问器属性。
class Person {
  constructor(name, age) {
    this._name = name;
    this._age = age;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    this._name = value;
  }
}

var person = new Person("Tom", 20);
console.log(person.name); // 输出 "Tom"
person.name = "Jerry";
console.log(person.name); // 输出 "Jerry"

在上述例子中,通过getter和setter方法定义了name访问器属性,可以通过person.name进行属性的访问和修改。

类的类型检查

  • ES5中,可以使用instanceof运算符来判断对象的类型

instanceof 运算符通过检查对象的原型链来确定对象是否是某个构造函数的实例。它会逐级向上查找对象的 __proto__(或 prototype)属性,直到找到与指定构造函数的 prototype 属性相等的对象或到达原型链的末尾。如果找到了相等的对象,则返回 true,否则返回 false

function Person() {}
var person = new Person();
console.log(person instanceof Person); // 输出 true
  • ES6中,可以使用typeof运算符来判断类的类型
class Person {}
var person = new Person();
console.log(typeof person); // 输出 "object"
console.log(typeof Person); // 输出 "function"

在上述例子中,typeof person返回objecttypeof Person返回function,可以看出,在ES6中类的类型也是object,类本身的类型是function文章来源地址https://www.toymoban.com/news/detail-666015.html

到了这里,关于ES5 的构造函数和 ES6 的类有什么区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 谈谈ES5和ES6的区别

    我们都知道JavaScript是由三部分组成: 1. ECMAScript(核心):规定了语言的组成部分=语法、类型、语句、、保留字、操作符、对象 2. BOM(浏览器对象模型): 支持访问和操作浏览器窗口,可以控制浏览器显示页面以外的部分。 3. DOM(文档对象模型): 把整个页面映射为一个多层节

    2024年02月02日
    浏览(27)
  • this在Es5和Es6的区别

    在ES5和ES6中,this的指向有所不同。 在ES5中,this的默认指向是全局对象(在浏览器环境中通常是window对象)。在函数中,this的指向取决于函数的调用方式。例如,在方法调用中,this指向调用该方法的对象;在构造函数中,this指向构造出来的新对象;在定时器或事件处理函数

    2024年01月19日
    浏览(24)
  • JavaScript、TypeScript、ES5、ES6之间的联系和区别

    ECMAScript:  一个由 ECMA International 进行标准化,TC39 委员会进行监督的语言。通常用于指代标准本身。 JavaScript:  ECMAScript 标准的各种实现的最常用称呼。这个术语并不局限于某个特定版本的 ECMAScript 规范,并且可能被用于任何不同程度的任意版本的 ECMAScript 的实现。 ECMAS

    2024年02月13日
    浏览(31)
  • 构造函数及es6类写单例模式

            前言,什么叫做单例模式?简单点说, 单例模式就是只能创建一个由构造函数及类的实体,多次调用得到的都是第一次new出来的对象 。用处有,例如在需要全局管理的资源、频繁访问的配置信息、日志记录器、 数据库连接池 等情况下都可以使用单例模式来优化资

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

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

    2024年02月16日
    浏览(27)
  • JavaScript版本ES5/ES6及后续版本

    Brendan Eich在短短10天内创建了JavaScript的第一个版本。它被称为摩卡,但已经具备了现代JavaScript的许多基本特性! 为了吸引Java开发人员,Mocha先是更改为LiveScript,然后又更改为JavaScript然而,JavaScript与Java几乎没有任何关系; 微软推出了IE,从网景复制JavaScript,并称之为JScript; 由

    2024年02月13日
    浏览(35)
  • 【ES5和ES6】数组遍历的各种方法集合

    特点: 没有返回值,只是针对每个元素调用func 三个参数:item, index, arr ;当前项,当前项的索引,被遍历的数组 for 循环可以在循环体中终止或跳过该循环,forEach不可以 特点:返回新的arr, 每个元素为调用函数返回的结果 参数: function:必选,数组中每个元素都会执行的函

    2024年02月12日
    浏览(26)
  • 【ES6】箭头函数和普通函数的区别

    它们之间的区别: (1)箭头函数没有自己的this。 (2)不可以当作构造函数,不可以对箭头函数使用new命令,否则抛出错误。 (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。 (4)不可以使用yield命令,箭头函数不能用作 Generator

    2024年02月12日
    浏览(24)
  • JavaScript Es6_2笔记 (深入对象 + 内置构造函数 + 包装类型)+包含实例方法

    了解面向对象编程的基础概念及构造函数的作用,体会 JavaScript 一切皆对象的语言特征,掌握常见的对象属性和方法的使用。 了解面向对象编程中的一般概念 能够基于构造函数创建对象 理解 JavaScript 中一切皆对象的语言特征 理解引用对象类型值存储的的

    2024年02月12日
    浏览(38)
  • 【微信小程序 | 实战开发】实现ES6转ES5开关

    你是否想要掌握人工智能的最新技术和应用?你是否想要成为未来社会的创新者和领导者?你是否想要和全球的优秀导师和同学一起学习和交流?如果你的答案是肯定的,那么欢迎来到床长人工智能教程网站,这里是你实现梦想的起点! 个人名片: 🐼 作者简介:一名大二在

    2024年02月11日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包