ES6 class private variables defined in the class

ES6 class private variables defined in the class

Lack of class Class

Look, es6 in class appeared narrowed the distance between JS and traditional OOP languages. However, it is only a syntactic sugar fills the traditional OOP language can not achieve the same functionality. In which a relatively large sore point is the issue of private variables.

What is a private variable? Variables Private variables that can only be accessed inside the class, can not access external variables. In development, many variable or method you do not want other people to access, can be defined as private variables, to prevent use by other people. In Java, you can use private achieve private variables, but Unfortunately, JS and without this feature.

Look at the following codes:

class A {
    constructor(x) {
        this.x = x
    }
    
    // 想要通过该方法来暴露x
    showX () {
        return this.x
    }
}

let a = new A(1)

// 直接访问x成功
a.x // 1

You can see that although the intention is to expose the value of x by method showX, but can directly access the value of x directly by the ax.

Clearly, this code affects encapsulation. You know, these are the attributes you can use for ... in to traverse out.

Therefore, to achieve functional class private variables are necessary.

Achieve class private variables

Although, class itself does not provide a function private variables, however, we can achieve functions similar to a private variable by some way.

  1. Naming conventions

    First, it is the most widely used way: Naming conventions.

    The way is very simple, that is one kind of team to agree on behalf of the named private variables, usually coupled with an underscore in front of the name of private variables. code show as below:

    class A {
        constructor(x) {
            // _x 是一个私有变量
            this._x = x
        }
    
     showX () {
         return this._x
     }
    
    }
    
    let a = new A(1)
    
    // _x 依然可以被使用
    a._x        // 1
    a.showX()   //1

    Can be found, the biggest advantage of this method is simple, convenient, so many teams have adopted this approach.

    However, this method does not solve the problem in essence, if you still can use for ... in traversing the so-called private variables, can be said to be a temporary solution.

    However, the way one thing is worthy of recognition, that is, by convention specification for others to read the code.

  2. Closure
    closure is used to solve the problem of modularity in many cases, it is clear the private variable nature of the problem is a modular, so we can use closures to solve the problem of private variables.

    In the constructor we define a local variable, and then by reference method, this variable becomes a real private variables.

    class A {
        constructor (x) {
            let _x = x
            this.showX = function () {
                return _x
            }
        }
    }
    
    let a = new A(1)
    // 无法访问
    a._x        // undefined
    // 可以访问
    a.showX()   // 1

    The biggest advantage is that the method solves the problem of the nature of private variables.

    But there is a big problem, in this case, the reference method private variables can not be defined on the prototype chain, can only be defined in the constructor, which is on the instance. This leads to two disadvantages:

    • Adds additional performance overhead

    • Contains the constructor method, it is cumbersome, causing some trouble subsequent maintenance

  3. Premium closures way

    Since within the definition of a constructor closures so much trouble, I placed outside class can not it do?

    • We can build a closure by IIFE (execution function expression immediately)
    • In which the establishment of a variable and class, reference variables to achieve private variables through class.

    code show as below:

    // 利用闭包生成IIFE,返回类A
    const A = (function() {
        // 定义私有变量_x
        let _x
    
     class A {
         constructor (x) {
             // 初始化私有变量_x
             _x = x
         }
    
         showX () {
             return _x
         }
     }
    
     return A
    
    })()
    
    let a = new A(1)
    
    // 无法访问
    a._x        // undefined
    // 可以访问
    a.showX()   //1

    You can find the perfect method to solve the problem before the closure, but the wording is relatively complex, will also need to create additional IIFE, there is little performance overhead.

    • Note: This mode may not be used IIFE, it can be directly placed in the global private variable, but this is not conducive to encapsulation.
  4. Symbol
    in this way is the use of Symbol's uniqueness - the biggest advantage is the enemy know our key value, the key value I ended up only, the enemy does not know my key values, no you can not access it? (The hostages is the key to the mission, when the enemy no longer has the hostages, the task is finished)

    code show as below:

    class A {
        constructor (x) {
    
            // 定义symbol
         const _x = Symbol('x')
    
            // 利用symbol声明私有变量
            this[_x] = x
        }
    
        showX () {
            return this[_x]
        }
    }
    
    let a = new A(1)
    
    // 1. 第一种方式
    a[_x]    // 报错 Uncaught ReferenceError: _x is not defined
    
    // 2. 第二种方式
    // 自行定义一个相同的Symbol
    const x = Symbol('x')
    a[x]        // 无法访问,undefined
    
    // 3. 第三种方式,可以访问(正解)
    a.showX()   //1

    From the results, the perfect realization of the class private variables.

Guess you like

Origin www.cnblogs.com/guojbing/p/10990267.html