详解ES6实现类的私有变量的几种写法

闭包实现类的私有变量方式

私有变量不共享

通过 new 关键字 person 的构造函数内部的 this 将会指向 Tom,开辟新空间,再次全部执行一遍,

class Person{
    constructor(name){
      let _num = 100; 

      this.name = name;
      this.getNum = function(){
        return _num;
      }
      this.addNum = function(){
        return ++_num
      }
    }
  }

  const tom = new Person('tom')
  const jack = new Person('jack')
  tom.addNum()
  console.log(tom.getNum()) //101
  console.log(jack.getNum()) //100

私有变量可共享

为避免每个实力都生成了一个新的私有变量,造成是有变量不可共享的问题,我们可以将这个私有变量放在类的构造函数到外面,继续通过闭包来返回这个变量。

const Person = (function () {
    let _num = 100;

    return class _Person {
      constructor(name) {
        this.name = name;
      }
      addNum() {
       return ++_num
      }
      getNum() {
       return _num
      }
    }
  })() 

  const tom = new Person('tom')
  const jack = new Person('jack')
  tom.addNum()
  console.log(tom.getNum()) //101
  console.log(jack.getNum()) //101 

那这样的话,如果两种方法混合使用,那就可以拥有可共享和不可共享的两种私有变量。

缺点:实例化时会增加很多副本,比较耗内存。

Symbol实现类的私有变量方式

symbol 简介:

创建一个独一无二的值,所有 Symbol 两两都不相等,创建时可以为其添加描述Symble("desc"),目前对象的健也支持 Symbol 了。

const name = Symbol('名字')
const person = { // 类名
  [name]:'www',
  say(){
    console.log(`name is ${this[name]} `)
  }
}
person.say()
console.log(name)

使用Symbol为对象创建的健无法迭代和Json序列化,所以其最主要的作用就是为对象添加一个独一无二的值。
但可以使用getOwnProporitySymbols()获取Symbol.
缺点:新语法浏览器兼容不是很广泛。

symbol 实现类的私有变量

推荐使用闭包的方式创建 Symbol 的的引用,这样就可以在类的方法区获得此引用,避免方法都写在构造函数,每次创建新实例都要重新开辟空间赋值方法,造成内存浪费。

const Person = (function () {
 let _num = Symbol('_num:私有变量');

 return class _Person {
  constructor(name) {
   this.name = name;
   this[_num] = 100
  }
  addNum() {
   return ++this[_num]
  }
  getNum() {
   return this[_num]
  }
 }
})()

const tom = new Person('tom')
const jack = new Person('jack')

console.log(tom.addNum()) //101
console.log(jack.getNum()) //100

通过 weakmap 创建私有变量

MDN 简介

实现:

const Parent = (function () {
 const privates = new WeakMap();

 return class Parent {
  constructor() {
   const me = {
    data: "Private data goes here"
   };
   privates.set(this, me);
  }
  getP() {
   const me = privates.get(this);
   return me
  }
 }
})()

let p = new Parent()
console.log(p)
console.log(p.getP())

总结

综上 weakmap 的方式来实现类似私有变量省内存,易回收,又能够被更多的浏览器兼容,也是最推荐的实现方法。

到此这篇关于详解ES6实现类的私有变量的几种写法的文章就介绍到这了,更多相关ES6 类的私有变量内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解ES6系列之私有变量的实现

    前言 在阅读 <ECMAScript 6 入门>的时候,零散的看到有私有变量的实现,所以在此总结一篇. 1. 约定 实现 class Example { constructor() { this._private = 'private'; } getName() { return this._private } } var ex = new Example(); console.log(ex.getName()); // private console.log(ex._private); //

  • 详解ES6实现类的私有变量的几种写法

    闭包实现类的私有变量方式 私有变量不共享 通过 new 关键字 person 的构造函数内部的 this 将会指向 Tom,开辟新空间,再次全部执行一遍, class Person{ constructor(name){ let _num = 100; this.name = name; this.getNum = function(){ return _num; } this.addNum = function(){ return ++_num } } } const tom = new Pe

  • 详解ES6之用let声明变量以及let loop机制

    在上一篇对js闭包的理解那篇文章中,我提到过ES6之前,JavaScript这门语言没有块级作用域,但是在ES6中,加入了let命令,用let声明的变量仅仅可以在其所在的块级作用域中使用. 相比用var声明,let声明的特点 1.let声明的变量仅在该变量所在的作用域有效 for(let i=0;i<5;i++){} console.log(i); //报错 for(var i=0;i<5;i++){} console.log(i); //i=5; 2.不存在变量提升 先解释下变量提升:变量提

  • 详解ES6语法之可迭代协议和迭代器协议

    ECMAScript 2015的几个补充,并不是新的内置或语法,而是协议.这些协议可以被任何遵循某些约定的对象来实现. 有两个协议:可迭代协议和迭代器协议. 可迭代协议 可迭代协议允许 JavaScript 对象去定义或定制它们的迭代行为, 例如(定义)在一个 for..of 结构中什么值可以被循环(得到).一些内置类型都是内置的可迭代对象并且有默认的迭代行为, 比如 Array or Map, 另一些类型则不是 (比如Object) . Iterator 接口的目的,就是为所有数据结构,提供了

  • 详解ES6 CLASS在微信小程序中的应用实例

    ES6 CLASS基本用法 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } 1.1 constructor方法 constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法.一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加.

  • 详解java自定义类

    引用数据类型(类) 引用数据类型分类 提到引用数据类型(类),其实我们对它并不陌生,之前使用过的Scanner类.Random类. 我们可以把类的类型为两种: 第一种,Java为我们提供好的类,如Scanner类,Random类等,这些已存在的类中包含了很多的方法与属性,可供我们使用. 第二种,我们自己创建的类,按照类的定义标准,可以在类中包含多个方法与属性,来供我们使用. 这里我们主要介绍第二种情况的简单使用. 自定义数据类型概述 我们在Java中,将现实生活中的事物抽象成了代码.这时,我们可

  • JVM详解之汇编角度理解本地变量的生命周期

    简介 java方法中定义的变量,它的生命周期是什么样的呢?是不是一定要等到方法结束,这个创建的对象才会被回收呢? 带着这个问题我们来看一下今天的这篇文章. 本地变量的生命周期 在类中,变量类型有类变量,成员变量和本地变量. 本地变量指的是定义在方法中的变量,如果我们在方法中定义了一个变量,那么这个变量的生命周期是怎么样的呢? 举个例子: public void test(){ Object object = new Object(); doSomeThingElse(){ ... } } 在上面

  • 详解ES6中class的实现原理

    一.在ES6以前实现类和继承 实现类的代码如下: function Person(name, age) { this.name = name; this.age = age; } Person.prototype.speakSomething = function () { console.log("I can speek chinese"); }; 实现继承的代码如下:一般使用原型链继承和call继承混合的形式 function Person(name) { this.name =

  • 详解Java String类常用方法有哪些

    一.构造器 实质是给底层的char数组value赋值 String s1 = new String(); String s2 = new String("abc"); String s3 = new String(new char[]{'a','b','c'}); 二.方法 str.length() 字符串长度本质是底层的char数组的长度 str.isEmpty() 本质是判断底层char数组长度是否为0 str.charAt(i) 本质是取底层char数组的第i个元素(字符) st

  • 详解 MAC/Linux Vi配置环境变量及Java环境变量配置

    详解 MAC/Linux Vi配置环境变量及Java环境变量配置 vi基础 1.vi的基本概念 (1)基本上vi可以分为三种状态,分别是命令模式(command mode).插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下: 1) 命令行模式command mode) 控制屏幕光标的移动,字符.字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode. 2) 插入模式(Insert mode) 只有在Ins

  • 详解ES6新增字符串扩张方法includes()、startsWith()、endsWith()

    当有人问到用来确定一个字符串是否包含在另一个字符串中有哪些方法时,我们会不假思索回答道:indexOf方法.其实,ES6 又提供了三种新方法includes().startsWith().endsWith(),也是比较好用的. indexOf方法在这里就不多说了,大家都比较熟悉,意思就是:返回给定元素在数组中第一次出现的位置,返回结果是匹配开始的位置,如果没有出现则返回-1. 下面详细介绍ES6新增的这三种方法: ①includes():返回布尔值,表示是否找到了参数字符串. 如下所示: let

随机推荐