JavaScript实现私有成员

作者: Quilljou | 来源:发表于2017-07-07 22:18 被阅读105次

JavaScript从某些角度来看是一门残缺的语言,即使es6在语法层面上实现了类和继承,但也只不过是语法糖而已,而且还没有实现私有成员。

当然,JavaScript没有什么不能靠hack来实现的,下面介(摘)绍(抄)一下几种模拟出私有成员的方法。

基于约定

如果使用ES6,约定以下划线_开头的成员名作为私有成员。

class Animal {
  constructor() {
    this._notPublicProperty = 2
  }
  _notPublicMethod () {
    return this._notPublicProperty
  }
}

这样貌似也勉强够用,但是只能靠使用者的自觉,遵守命名规则。

ES5基于闭包

function  Animal() {
}

Animal.prototype = (function () {
  var self = this;
  var _notPublicProperty = 2;
  function _notPublicMethod() {
    return _notPublicProperty;
  }

  return {
    constructor: Animal,
    getNotPublicProperty: function() {
      return _notPublicMethod.call(this)
    }
  }
}())

var dog = new Animal()
console.log(dog.getNotPublicProperty());  // 2
console.log(dog._notPublicMethod());  // ReferenceError: _notPublicProperty is not defined

Symbol

复习一下JavaScript的六种基本数据类型

undefined null number string object boolean

ES6为JavaScript引入了一种新的基本数据类型 -- Symbol
Symbol是一个全局函数,每调用一次就会产生一个唯一的字符串,关于Symbol的详细介绍可以参见 阮一峰的ES6教程

const _notPublicMethod = Symbol()
const _notPublicProperty = Symbol()
class Animal {
  constructor() {
    this[_notPublicProperty] = 2;
  }
  [_notPublicMethod]() {
    return this[_notPublicProperty]; // 必须用中括号
  }
  getNotPublicProperty() {
    return this[_notPublicMethod]()
  }
}

var dog = new Animal()

console.log(dog.getNotPublicProperty());  // 2
console.log(dog._notPublicMethod());  // ReferenceError: _notPublicProperty is not defined

每次都要创建一个Symbol还是不那么完美,但是已经不错了。

WeakMap

Map和WeakMap都是ES6新引入的数据结构。
Map和Object类似,都是hash结构。Object的键只能是字符串,而Map打破了这一限制,键可以是任意数据类型,而WeakMap比Map要弱一点,键只能是对象;且WeakMap的键名所指向的对象,不计入垃圾回收机制。

主要的思路是,在类的级别上创建一个 WeakMap 容器,用于存储各个实例的私有成员


const store = new WeakMap()

class Animal {
  constructor() {
    var self = this;

    function _notPublicMethod() {
      return store.get(this)._notPublicProperty
    }

    store.set(this,{
      _notPublicProperty: 2,
      _notPublicMethod: _notPublicMethod.bind(self)
    })
  }

  getNotPublicProperty() {
    return store.get(this)._notPublicMethod
  }
}

var dog = new Animal()

console.log(dog.getNotPublicProperty());  // 2
console.log(dog._notPublicMethod());  // ReferenceError: _notPublicProperty is not defined

貌似引入WeakMap使得问题更加复杂,还是我的打开方式不对?

最后,还是希望babel和node能够尽快支持最新的提案,使用#来自然的标识私有成员,写hack真的很hack啊!

参考

相关文章

  • JavaScript实现私有成员

    JavaScript从某些角度来看是一门残缺的语言,即使es6在语法层面上实现了类和继承,但也只不过是语法糖而已,...

  • OC中如何实现私有成员变量

    OC中如何实现私有成员变量 @property生成的成员变量即为私有成员变量@property生成的是: 带下划线...

  • Objective-C Runtime API的应用

    查看私有成员变量 获取到成员变量的名称,就能通过KVC为私有成员变量设置值,比如 替换方法实现,交换方法 clas...

  • iOS 如何访问私有变量

    方法1: 如果你能看到类的实现以及私有成员,可以使用kvc 设置私有成员: - (void)setValue:(n...

  • JacaScript 私有变量(一)什么是私有变量

    严格来讲,JavaScript 中没有私有成员的概念;所有对象属性都是公有的。不过,倒是有一个私有变量的概念。 任...

  • 【javascript】私有变量

    严格来讲,JavaScript 中没有私有成员的概念;所有对象属性都是公有的。 有一个私有变量的概念。任何在函数中...

  • 【C++面向对象备忘录】1 基础

    类定义的一般格式 数据成员一般是私有的 成员函数一般是公有的 成员函数实现时分解出的小函数是私有的 this指针 ...

  • JavaScript:公有、私有、特权和静态成员

    作用域链是用来描述一种路径的术语,沿着该路径可以确定变量的值(或者当函数调用时要使用的方法)。本质上说var关键字...

  • Python 入门 之 类成员

    1、类的私有成员: 私有: 只能自己拥有 以 __ 开头就是私有内容 ​ 为什么可以通过.类__私有成员名访问呢?...

  • 内部类

    内部类:可以继承,可以实现接口 内部类,可以使用外部成员,包括私有 外部类,使用内部类成员,必须建立 内部类...

网友评论

    本文标题:JavaScript实现私有成员

    本文链接:https://www.haomeiwen.com/subject/gowrhxtx.html