前言
ES6 作为一个重要的 JavaScript 规范,为 JavaScript 程序员带来了很多新的特性。其中最重要的就是 class 关键字。
ES6 中的 class 拓展了 JavaScript 的语法,使得我们可以更加方便地使用面向对象编程的方式。然而,对于初学者来说,这种新的语法可能会感到有些陌生,比如与原型链的关系。
因此,本文将深入探讨 ES6 中的 class 和 prototype,帮助读者更深入的理解面向对象编程的原理和操作方式。
1. ES6 中的 class
在 ES6 之前,JavaScript 中没有专门用于对象生成的关键字。通常我们使用函数来创建一个对象,然后用 prototypes 来扩展对象的属性和方法。
但是,ES6 中引入了 class 关键字,可以用来更加简单明了地定义对象和类的结构。
与其它面向对象编程语言的 class 关键字略有不同,JavaScript 中的 class 实际上还是构造函数的语法糖,即用 class 定义类的本质还是函数的定义,只不过让我们使用起来更加方便了。
下面是一个基本的 class 的定义:
// javascriptcn.com 代码示例 class Square { constructor(side) { this.side = side; } get area() { return this.side * this.side; } set area(value) { this.side = Math.sqrt(value); } }
- constructor 是一个特殊的方法,用于创建和初始化对象。instance 创建后会调用 constructor 方法。除了 constructor 之外,还有其它的特殊方法,如 getter/setter 方法,抽象方法等,详情可以参考 class。
- get 和 set 的方法名必须是一样的,用于访问变量的属性值,即类似于 Java 中的 getter 和 setter 方法。
现在我们创建一个 Square 实例,并设置其 area 属性值为 64,然后打印出值:
let square = new Square(5); square.area = 64; console.log(square.side); // 输出 8
结合上述代码,我们可以看到 class 的定义语法是更加简单、优雅的,并将相关属性和方法封装在一个体系结构之中。
2. ES6 中的 prototype
在 ES5 中,原型链是 JavaScript 实现类的核心。当我们使用函数生成一个对象时,实际上会生成一个带有一组特殊属性和方法的对象,这些属性和方法可以扩展和重载函数。
这个对象被称为构造函数的 prototype。实际上,所有使用该构造函数创建的对象都会共享该 prototype 对象。
下面是一个使用 prototype 创建对象的示例代码:
// javascriptcn.com 代码示例 function Triangle(base, height) { this.base = base; this.height = height; } Triangle.prototype.area = function() { return 0.5 * this.base * this.height; }; let triangle = new Triangle(4, 5); console.log(triangle.area()); // 输出 10
在上面的代码中,我们创建了一个 Triangle 的构造函数,并在 prototype 上定义了一个 area 方法。在构造函数中,我们初始化了 base 和 height 属性,最后返回的是这个对象的面积。在调用 area 方法时,JavaScript 引擎会先查找实例对象的属性和方法,如果没有找到,则会顺着原型链查找 prototype 对象的属性和方法。
3. class 和 prototype 的关系
在 ES6 中,我们可以使用 class 创建一个类,但是该类的本质实际上还是一个函数。在这个函数创建的对象中,也有一个对应的 prototype 对象。
因此,在 class 中定义的属性和方法也可以被复写或者访问。我们也可以通过 super 关键字调用父类定义的属性和方法。
下面是一个使用 class 和 prototype 的演示代码:
// javascriptcn.com 代码示例 class Shape { constructor(name) { this.name = name; } print() { console.log(`I am a ${this.name}.`); } } class Rectangle extends Shape { constructor(length, width) { super("Rectangle"); this.length = length; this.width = width; } get area() { return this.length * this.width; } set area(value) { this.length = Math.sqrt(value); this.width = Math.sqrt(value); } print() { super.print(); console.log(`My area is ${this.area}.`); } } let rectangle = new Rectangle(4, 5); rectangle.area = 25; rectangle.print();
在上述代码中,我们首先定义了一个 Shape 的 class,其中包含了一个 print() 方法。接下来,我们又定义了一个 Rectangle 的 class,继承自 Shape。在 Rectangle 中我们定义了一个 area 属性和 getter/setter 方法。在 print() 方法中,我们调用了超类的方法,并打印了 rectangle 的内部状态。
最终,我们创建了一个 Rectangle 的实例,将它的 area 设为 25 并输出了这个实例的信息。
总结
本文深入探讨了 ES6 中的 class 和 prototype 的关系。我们了解了 class 实际上是构造函数的语法糖,用以方便生成一个对象类的结构。并且,我们还详细讲解了 prototype 的基本原理和使用方法,以及 class 和 prototype 之间的关系。
深入理解 class 和 prototype 可以让我们更好的使用面向对象编程,更加熟练掌握 JavaScript 等编程语言的特性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6538bde67d4982a6eb1ba495