JavaScript 是一门典型的面向对象编程语言,其中 prototype 和 class 是两个重要的概念。ECMAScript 2021 引入了一些新特性来优化它们的使用。本文将详细介绍 prototype 和 class 的概念及其在 JavaScript 中的应用。
prototype
JavaScript 中的每个对象都包含一个隐式的 prototype 属性。它指向另一个对象,称为原型对象。该原型对象也可能具有自己的原型对象,形成一个 “原型链” 用于继承性质。对象可以访问其原型对象上的所有属性和方法。
假设我们有如下的一个对象:
-- -------------------- ---- ------- ----- ------ - -------------- ---- - --------- - ----- -------- - ---- -- ------------------------- - ---------- - ------------------- -- ---- -- --------------- -- ----- ---- - --- -------------- ---- ---------------- -- ------ -- ---- -- ----
在上面的例子中,我们使用了构造函数来创建一个名为 Person 的对象,并将其原型对象添加了一个名为 sayHello 的方法。在创建实例 jack 后,我们可以调用其原型对象中的 sayHello 方法。
console.log(Object.getPrototypeOf(jack) === Person.prototype); // true
此时我们还可以修改原型对象中的属性和方法:
Person.prototype = { eat() { console.log(`${this.name} is eating.`); } }; jack.eat(); // TypeError: jack.eat is not a function
因为我们修改了 Person 的原型对象,导致 jack 不再关联到其原型对象,从而无法调用原型上的 eat 方法。这种变化通常应该在创建实例之前进行。
class
class 是 ECMAScript 2015 引入的一种语法糖,以更自然的方式定义构造函数并创建对象,可以视为 prototype 的一种替代方式。
使用 class 定义 Person 对象等价于使用构造函数定义:
-- -------------------- ---- ------- ----- ------ - ----------------- ---- - --------- - ----- -------- - ---- - ---------- - ------------------- -- ---- -- --------------- - -
它们的实例创建方式也相同:
const jack = new Person('Jack', 20); jack.sayHello(); // Hello, my name is Jack
class 还支持 extends 和 super 关键字,让我们可以方便地实现继承:
-- -------------------- ---- ------- ----- ------ - ----------------- - --------- - ----- - ------- - ------------------------- ----- - --------- - - ----- --- ------- ------ - ------- - ------------------------- --------- - - ----- --- - --- ------------- ------------ -- ----- ------
ECMAScript 2021 新特性
ECMAScript 2021 引入了一些新特性,用于简化面向对象编程中的一些操作:
简化原型对象
我们可以使用 Object.setPrototypeOf 方法以及 proto 属性来修改对象的原型链。但是这样做会影响代码性能,因为它会导致运行时进行属性查找、方法调用时的性能开销。在 ECMAScript 2021 中,我们可以使用 Object.create 方法来构建对象的原型,并指定对象的属性和方法:
-- -------------------- ---- ------- ----- ----------- - - ---------- - ------------------- -- ---- -- --------------- - -- ----- ---- - -------------------------- - ----- - ------ ------ -- ---- - ------ -- - --- ---------------- -- ------ -- ---- -- ----
这样做的好处是,在对象原型中添加新属性或方法时,无需修改其他对象,同时使代码更具可读性。
私有字段
常见的面向对象编程方法将对象的状态保留在对象本身中。但是在 JavaScript 中,我们通常使用外部变量来实现这一点。ECMAScript 2021 引入了私有字段,使得状态可以完全封装在对象内部。它们可以在类中使用 # 开头的标识符来声明:
-- -------------------- ---- ------- ----- ------ - ------ ----------------- - ---------- - ----- - --------- - ------ ----------- - ------------- - ---------- - ----- - - ----- ---- - --- --------------- ---------------------------- -- ---- -------------------- ---------------------------- -- --- ------------------------ -- -------- ------------ ------- ----- ------- ---- -- -------- -- -- --------- -----
此时,我们无法直接访问 #name 属性,因为它是私有的。只能通过 getName 和 setName 方法来获取和修改其值。
总结
prototype 和 class 是 JavaScript 中非常重要的概念,它们实现了面向对象编程的封装、继承和多态等特性。ECMAScript 2021 引入了新特性以简化这些操作。在使用面向对象编程时,我们应该充分理解这些概念的本质,灵活应用它们,以实现更优雅、更高效的代码。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6542371c7d4982a6ebbe253f