位置: 编程技术 - 正文

基于JavaScript如何实现私有成员的语法特征及私有成员的实现方式(javascript教程chm)

编辑:rootadmin

推荐整理分享基于JavaScript如何实现私有成员的语法特征及私有成员的实现方式(javascript教程chm),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:javascript编写,javascript教程chm,javascript基础,javascript编写,javascript基于什么的语言,用javascript,用javascript,javascript基于什么的语言,内容如对您有帮助,希望把文章链接给更多的朋友!

前言

在面向对象的编程范式中,封装都是必不可少的一个概念,而在诸如 Java,C++等传统的面向对象的语言中, 私有成员是实现封装的一个重要途径。但在 JavaScript 中,确没有在语法特性上对私有成员提供支持, 这也使得开发人员使出了各种奇技淫巧去实现 JS 中的私有成员,以下将介绍下目前实现 JS 私有成员特性的几个方案以及它们之间的优缺点对比。

现有的一些实现方案

约定命名方案

约定以下划线'_'开头的成员名作为私有成员,仅允许类成员方法访问调用,外部不得访问私有成员。简单的代码如下:

JavaScript

优点

毫无疑问,约定命名是最简单的私有成员实现方案,没有代码层面上的工作。调试方便,能够在控制台上直接看到对象上的私有成员,方便排查问题。兼容性好,ie6+都支持

不足

无法阻止外部对私有成员的访问和变更,如果真有不知道或者不遵守约定的开发人员变更私有属性,也是无能为力。必须强制或说服大家遵守这个约定,当然这个在有代码规范的团队中不是什么太大的问题。

es6 symbol 方案

在 es6中,引入了一个 Symbol 的特性,该特性正是为了实现私有成员而引入的。主要的思路是,为每一个私有成员的名称产生一个随机且唯一的字符串key,这个 key 对外不可见,对内的可见性则是通过 js 的闭包变量实现,示例代码如下:

JavaScript

优点

弥补了命名约定方案的缺陷,外部无法通过正常途径获得私有成员的访问权。调试便捷程度上可以接受,一般是通过给 symbol 的构造函数传入一个字符串参数,则控制台上对应的私有属性名称会展示为:Symbol(key)

兼容性不错,不支持 Symbol的浏览器可以很容易的 shim 出来。

不足

写法上稍显别扭,必须为每一个私有成员都创建一个闭包变量让内部方法可以访问。外部还是可以通过 Object.getOwnPropertySymbols的方式获取实例的 symbol 属性名称,通过该名称获得私有成员的访问权。这种场景出现得比较少,且知道这种途径的开发人员水平相信都是有足够的能力知道自己的行为会有什么影响,因此这个不足点也算不上真正意义的不足。

es6 WeakMap 方案

在 es6 中引入了 Map, WeakMap 容器,最大的特点是容器的键名可以是任意的数据类型,虽说初衷不是为了实现私有成员引入,但意外的可以被用来实现私有成员特性。

主要的思路是,在类的级别上创建一个 WeakMap 容器,用于存储各个实例的私有成员,这个容器对外不可见,对内通过闭包方式可见;内部方法通过将实例作为键名获取容器上对应实例的私有成员,示例代码如下:

JavaScript

优点

弥补了命名约定方案的缺陷,外部无法通过正常途径获得私有成员的访问权。对 WeakMap 做一些封装,抽出一个私有特性的实现模块,可以在写法上相对 Symbol 方案更加简洁干净,其中一种封装的实现可以查看参考文章3。最后一个是个人认为最大的优势:基于 WeakMap 方案,可以方便的实现保护成员特性(这个话题会在其他文章说到:))

基于JavaScript如何实现私有成员的语法特征及私有成员的实现方式(javascript教程chm)

不足

不好调试,因为是私有成员都在闭包容器内,无法在控制台打印实例查看对应的私有成员待确认的性能问题,根据 es6的相关邮件列表,weakmap 内部似乎是通过顺序一一对比的方式去定位 key 的,时间复杂度为 O(n),和 hash 算法的 O(1)相比会慢不少

最大的缺陷则是兼容性带来的内存膨胀问题,在不支持 WeakMap 的浏览器中是无法实现 WeakMap 的弱引用特性,因此实例无法被垃圾回收。 比如示例代码中 privateProp 是一个很大的数据项,无弱引用的情况下,实例无法回收,从而造成内存泄露。

现有实现方案小结

从上面的对比来看,Symbol方案最大优势在于很容易模拟实现;而WeakMap的优势则是能够实现保护成员, 现阶段无法忍受的不足是无法模拟实现弱引用特性而导致的内存问题。于是我的思路又转向了将两者优势结合起来的方向。

Symbol + 类WeakMap 的整合方案

在 WeakMap 的方案中最大的问题是无法 shim 弱引用,较次要的问题是不大方便调试。

shim 出来的 WeakMap 主要是无法追溯实例的生命周期,而实例上的私有成员的生命周期又是依赖实例, 因此将实例级别的私有成员部分放在实例上不就好了? 实例没了,自然其属性也随之摧毁。而私有存储区域的隐藏则可以使用 Symol 来做。

该方案的提供一个 createPrivate 函数,该函数会返回一个私有的 token 函数,对外不可见,对内通过闭包函数获得, 传入当前实例会返回当前实例的私有存储区域。使用方式如下:

JavaScript

代码中主要就是实现 createPrivate 函数,大概的实现如下:

JavaScript

上述实现做了两层存储,privateStore 这层是实例上统一的私有成员存储区域,而 classToken 对应的则是继承层次之间不同类的私有成员定义,基类有基类的私有成员区域,子类和基类的私有成员区域是不同的。

当然,只做一层的存储也可以实现,两层存储仅仅是为了调试方便,可以直接在控制台通过Symbol(‘privateStore')这个属性来查看实例各个层次的私有部分。

奇葩的 es5 property getter 拦截方案

该方案纯粹是闲得无聊玩了玩,主要是利用了 es5 提供的 getter,根据 argument.callee.caller 去判断调用场景,如果是外部的则抛异常或返回 undefined, 如果是内部调用则返回真正的私有成员,实现起来比较复杂,且不支持 strict 模式,不推荐使用。 有兴趣的同学可以看看实现。

总结

以上几个方案对比下来,我个人是倾向 Symbol+WeakMap 的整合方案,结合了两者的优点,又弥补了 WeakMap 的不足和 Symbol 书写的冗余。 当然了,我相信随着 JS 的发展,私有成员和保护成员也迟早会在语法层面上进行支持,正如 es6 对 class 关键字和 super 语法糖的支持一样, 只是现阶段需要开发者使用一些技巧去填补语言特性上的空白。

Javascript私有成员的实现方式

总体来讲这本书还是可以的,但看完这本书还留了几个问题一直困扰着我,如js中私有变量的实现,prototype等,经过自己一系列测试,现在终于弄明白了。

很多书上都是说,Javascript是不能真正实现Javascript私有成员的,因此在开发的时候,统一约定 __ 两个下划线开头为私有变量。

后来,发现Javascript中闭包的特性,从而彻底解决了Javascript私有成员的问题。

test._Name 根本访问不到,但是用对象方法能访问到,因为闭包能从当前的执行环境中获取信息。

接下来我们看看,共有成员是怎样实现的

接下来在看看类静态变量是怎样实现的

JS实现双击屏幕滚动效果代码 本文实例讲述了JS实现双击屏幕滚动效果代码。分享给大家供大家参考,具体如下:这里演示双击滚屏效果代码的实现方法,不知道有觉得有用处的没,

JavaScript多并发问题如何处理 经常在写代码的时候碰到这样的场景:页面初始化时显示loading页,同时启动多个ajax并发请求获取数据,当每个ajax请求返回时结束loading。举个例子,一

开启Javascript中apply、call、bind的用法之旅模式 我希望能够通过这篇文章,能够清晰的提升对apply、call、bind的认识,并且列出一些它们的妙用加深记忆。apply、call在javascript中,call和apply都是为了改变

标签: javascript教程chm

本文链接地址:https://www.jiuchutong.com/biancheng/382672.html 转载请保留说明!

上一篇:JavaScript如何调试有哪些建议和技巧附五款有用的调试工具(js怎么设置css)

下一篇:JS实现双击屏幕滚动效果代码(js实现双击屏幕放大)

  • 预缴增值税的账务
  • 银行日记账期初余额写在什么科目
  • 利润属于所有者权益类科目吗
  • 员工交通费属于什么费用
  • 农产品收购发票可以跨区域开吗
  • 不动产在建工程使用的外购物资可以抵扣吗
  • 私车公用产生的过路费怎么开发票
  • 母公司收购少数股东股权,之前的利润母公司不享有
  • 个体户需要交税吗要交多少
  • 铲车费属于劳务费吗
  • 软件的维修性要求
  • 小规模纳税人能抵扣进项发票吗
  • 账务不符怎么写
  • 个人交社保可以交生育险吗
  • 利润表没有其他业务利润
  • 税收筹划有哪些特点?
  • 事业单位年终事迹材料
  • 举办活动购买的东西会计分录
  • 冲销货款应怎么记账
  • macbook显示隐藏文件
  • windows11永久解决蓝屏
  • 魁北克位置地图
  • 结算备付金的账户是什么
  • jetcar.exe - jetcar是什么进程 有什么作用
  • 【安装 】
  • cesium加载s3m
  • PHP:image_type_to_extension()的用法_GD库图像处理函数
  • 纳税申报方式的税务申报工作常规流程图
  • 用现金报销差旅费,合规吗
  • 小企业会计准则财务报表至少包括
  • h5页面跳转小程序不显示按钮
  • 企业取得交易性金融资产时
  • 用于研发的材料后期销售了应该怎么账务处理
  • 富文本功能
  • 固定资产盘亏要改变资产原值吗
  • 工程材料税票怎样抵税
  • 证券公司收益凭证管理办法
  • 技术使用费 收费标准
  • 揭秘蟹卡骗局
  • 小企业会计准则2023电子版
  • 记账凭证基本内容口诀
  • 租入厂房再转租新租赁准则如何处理
  • 合伙律师事务所管理办法最新
  • 怎么计提固定资产的累计折旧
  • 制造企业费用会计
  • 非关联企业之间可以借款吗
  • 递延所得税资产和递延所得税负债
  • 哪些行为应作为证据
  • sql server常见故障
  • sql2000删除
  • centos7.6无法远程
  • MySQL 与 Elasticsearch 数据不对称问题解决办法
  • centos7怎么配置yum源
  • mysql嵌套查询联表查询
  • win8怎么运行
  • centos安装类型选择
  • 轻量级个人用linux桌面系统
  • win10如何关闭windows
  • win10 20h2 04累积更新
  • win8如何隐藏任务栏
  • [置顶]bilinovel
  • 文本框后缀
  • cocos2d开发的知名游戏
  • js脚本使用
  • javascript判断语句
  • node.js redis
  • js的document.getelembyid
  • 手机gpu过度绘制
  • 浅析学校德育的个体智能发展功能
  • unity as
  • 电子发票怎么汇总清卡
  • 中山市十大纳税大户
  • 国家税务总局发票查验平台网络异常
  • 个人所得税追缴很快就缴清了还会被罚款吗
  • 如何电子税务局缴纳社保费用
  • 补缴印花税分录
  • 上海二手房个税退税政策
  • 一般纳税人开具的增值税普通发票和专用发票的区别
  • popl期刊
  • 印花税会计分录怎么做 印花税需要计提吗
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设