耀极客论坛

 找回密码
 立即注册
查看: 443|回复: 0

JavaScript 中创建私有成员

[复制链接]

336

主题

318

帖子

22万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
220553
发表于 2022-5-9 01:49:25 | 显示全部楼层 |阅读模式
  这篇文章主要介绍了JavaScript 中创建私有成员,下面介绍以 # 作为前缀几种在 JavaScript 代码中实现私有属性和方法的方式,需要的小伙伴可以参考一下
  前言:
  面向对象编程语言中的 private 关键字是一个访问修饰符,可用于使属性和方法只能在声明的类中访问。这使得隐藏底层逻辑变得容易,这些底层逻辑应该被隐藏起来,并且不应该与类的外部交互。
  但是如何在 JavaScript 中实现类似的功能呢? 没有保留关键字 private ,但在新的标准中 JavaScript 有自己的方法来创建类私有成员,但目前还处于 ES2020 试验草案中,并且语法比较奇怪,以 # 作为前缀。下面介绍几种在 JavaScript 代码中实现私有属性和方法的方式。

1.使用闭包

  使用闭包可以使用私有属性或者方法的封装。利用闭包可以访问外部函数的变量特征。
  如下代码片段:
  1. function MyProfile() {
  2.     const myTitle = "DevPoint";
  3.     return {
  4.         getTitle: function () {
  5.             return myTitle;
  6.         },
  7.     };
  8. }
  9. const myProfile = MyProfile();
  10. console.log(myProfile.getTitle()); // DevPoint
复制代码
  这可以转化为将最顶层的自调用函数调用分配给一个变量,并且只用函数返回来公开它的一些内部函数:
  1. const ButtonCreator = (function () {
  2.     const properties = {
  3.         width: 100,
  4.         height: 50,
  5.     };
  6.     const getWidth = () => properties.width;
  7.     const getHeight = () => properties.height;
  8.     const setWidth = (width) => (properties.width = width);
  9.     const setHeight = (height) => (properties.height = height);
  10.     return function (width, height) {
  11.         properties.width = width;
  12.         properties.height = height;
  13.         return {
  14.             getWidth,
  15.             getHeight,
  16.             setWidth,
  17.             setHeight,
  18.         };
  19.     };
  20. })();
  21. const button = new ButtonCreator(600, 360);
  22. console.log(button.getHeight()); // 360
复制代码
2.使用 ES6 类

  为了使代码更类似于 OOP 方法,可以使用 ES6 中引入的 class 关键字。要使属性和方法私有,可以在类之外定义它们。
  就对上面的 ButtonCreator 的例子使用 class 进行重构:
  1. const properties = {
  2.     width: 100,
  3.     height: 50,
  4. };
  5. class ButtonCreator {
  6.     constructor(width, height) {
  7.         properties.width = width;
  8.         properties.height = height;
  9.     }
  10.     getWidth = () => properties.width;
  11.     getHeight = () => properties.height;
  12.     setWidth = (width) => (properties.width = width);
  13.     setHeight = (height) => (properties.height = height);
  14. }
  15. const button = new ButtonCreator(600, 360);
  16. console.log(button.getHeight()); // 360
复制代码
  现在假设属性是公共的,但想在私有方法中使用它们,其中上下文指向 ButtonCreator,可以通过以下方式实现它:
  1. const privates = {
  2.     calculateWidth() {
  3.         return this.width;
  4.     },
  5. };
  6. class ButtonCreator {
  7.     constructor(width, height) {
  8.         this.width = width;
  9.         this.height = height;
  10.     }
  11.     getWidth = () => privates.calculateWidth.call(this);
  12.     getHeight = () => this.height;
  13.     setWidth = (width) => (this.width = width);
  14.     setHeight = (height) => (this.height = height);
  15. }
  16. const button = new ButtonCreator(600, 360);
  17. console.log(button.getHeight()); // 360
复制代码
  上面的代码使用了 Function.prototype.call,它用于调用具有给定上下文的函数。在例子中,使用 ButtonCreator 类的上下文。
  如果私有函数也需要参数,可以将它们作为附加参数传递以调用:
  1. const privates = {
  2.     calculateWidth(percent) {
  3.         return this.width * percent;
  4.     },
  5. };
  6. class ButtonCreator {
  7.     constructor(width, height) {
  8.         this.width = width;
  9.         this.height = height;
  10.     }
  11.     getWidth = () => privates.calculateWidth.call(this, 0.1);
  12.     getHeight = () => this.height;
  13.     setWidth = (width) => (this.width = width);
  14.     setHeight = (height) => (this.height = height);
  15. }
  16. const button = new ButtonCreator(600, 360);
  17. console.log(button.getWidth()); // 60
复制代码
3.使用 ES2020 提案

  还处于 ES2020 试验草案中,引入了私有方法或者属性的定义,语法比较奇怪,以 # 作为前缀。
  1. class ButtonCreator {
  2.     #width;
  3.     #height;
  4.     constructor(width, height) {
  5.         this.#width = width;
  6.         this.#height = height;
  7.     }
  8.     // 私有方法
  9.     #calculateWidth() {
  10.         return this.#width;
  11.     }
  12.     getWidth = () => this.#calculateWidth();
  13.     getHeight = () => this.#height;
  14.     setWidth = (width) => (this.#width = width);
  15.     setHeight = (height) => (this.#height = height);
  16. }
  17. const button = new ButtonCreator(600, 360);
  18. console.log(button.width); // undefined
  19. console.log(button.getWidth()); // 600
复制代码
4.使用 WeakMap

  这种方法建立在闭包方法之上,使用作用域变量方法创建一个私有 WeakMap,然后使用该 WeakMap 检索与此相关的私有数据。这比作用域变量方法更快,因为所有实例都可以共享一个 WeakMap,所以不需要每次创建实例时都重新创建方法。
  1. const ButtonCreator = (function () {
  2.     const privateProps = new WeakMap();
  3.     class ButtonCreator {
  4.         constructor(width, height, name) {
  5.             this.name = name; // 公共属性
  6.             privateProps.set(this, {
  7.                 width, // 私有属性
  8.                 height, // 私有属性
  9.                 calculateWidth: () => privateProps.get(this).width, // 私有方法
  10.             });
  11.         }
  12.         getWidth = () => privateProps.get(this).calculateWidth();
  13.         getHeight = () => privateProps.get(this).height;
  14.     }
  15.     return ButtonCreator;
  16. })();
  17. const button = new ButtonCreator(600, 360);
  18. console.log(button.width); // undefined
  19. console.log(button.getWidth()); // 600
复制代码
  这种方式对于私有方法的使用有点别扭。

5.使用 TypeScript

  可以将 TypeScript 用作 JavaScript 的一种风格,可以使用 private 关键字从面向对象的语言中真正重新创建功能。
  1. class ButtonCreator {
  2.     private width: number;
  3.     private height: number;
  4.     constructor(width: number, height: number) {
  5.         this.width = width;
  6.         this.height = height;
  7.     }
  8.     private calculateWidth() {
  9.         return this.width;
  10.     }
  11.     public getWidth() {
  12.         return this.calculateWidth();
  13.     }
  14.     public getHeight() {
  15.         return this.height;
  16.     }
  17. }
  18. const button = new ButtonCreator(600, 360);
  19. console.log(button.getWidth()); // 600
  20. console.log(button.width); // error TS2341: Property 'width' is private and only accessible within class 'ButtonCreator'.
复制代码
  总结:

  到此这篇关于JavaScript 中创建私有成员的文章就介绍到这了,更多相关JavaScript 中创建私有成员内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|耀极客论坛 ( 粤ICP备2022052845号-2 )|网站地图

GMT+8, 2022-11-28 20:27 , Processed in 0.076402 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表