如何从构造(闭包)外部列出一个简单的私有变量?

How to list a simple private variable from outside a construct (closure)?

有没有办法在构造函数的上下文之外列出私有变量?

例如:

function Person() {
  let globalId = 10;
  this.listGlobalId = function() {
    return globalId;
  }
};

let alan = new Person;

现在我们将在 console.log of alan 之后得到像这样的东西:"Person { listGlobalId: [Function] }"

有没有办法从对象 alan 中恢复“globalId”?

要使 class 的 属性 私有化(只能从内部访问),您可以声明 属性 名称后跟#。然后您可以使用 getter.

访问您的私有变量

class Person {
  #globalId;
  
  constructor(name, globalId){
    this.name = name;
    this.#globalId = globalId;
  }
  
  get getGlobalId(){
    return this.#globalId;
  }
};

let alan = new Person('alan', 3);

console.log(alan.getGlobalId);    // 3
//console.log(alan.#globalId);    // Error

如果您正在寻找只能从 class 访问的方法,您可以使用静态方法:

class Person {
  constructor(name) {
    this._name = name;
  }
  static generateName() {       // You can call it directly from the class, but not from an instance of the class.
    const names = ['Angel', 'Pedro', 'Luis', 'Mario', 'Julio'];
    const randomNumber = Math.floor(Math.random()*5);
    return names[randomNumber];
  }
} 
console.log(Person.generateName());  // Returns a random name.

使用 this.#privateVariables 是主要方式,但 # 私有变量没有太多支持(撰写本文时约占 67%)。如果可以避免的话,我不喜欢转译,所以这里有一些有很多浏览器支持的解决方案。

// Code to match your example
function Person() {
  let globalId = 10;
  this.listGlobalId = function() {
    return globalId;
  }
  
  // Kind of like a getter
  this.iifeGlobalId = (function() {
    return globalId;
  })();
};

let alan = new Person;

console.log('Person getter ', alan.iifeGlobalId);
console.log('Person Object ', alan);

// Class Based solutions

class Adult {
  constructor() {
    let globalId = 10;
    this.globalId = 10;
  }
  
  // Kind of like #globalId
  // Except that __globalId will
  // still be listed if you log the
  // class
  set globalId(num) {
    if (!this.__globalId) this.__globalId = num;
  }
  
  get globalId() {
    return this.__globalId;
  }
}

const adultAlan = new Adult;

console.log('Adult pseudo private properties ', adultAlan.globalId)
console.log('Adult __globalId still shows up ', { adultAlan })

const privateMap = new Map();

class PrivateAdult {
  constructor() {
    privateMap.set(this, {
      globalId: 10,
      otherSecret: 'banana bread'
    });
  }
  
  get globalId() {
    const instance = privateMap.get(this);
    return instance.globalId;
  }
}

/**
  This PrivateAdult class only works if you export the
  class from a module but keep the privateMap variable
  inside the original module. 
**/

const privateAlan = new PrivateAdult;

console.log('PrivateAdult ', privateAlan.globalId);
console.log('PrivateAdult keeps everything neat :) ', { privateAlan });
console.log('Get information from privateMap using the created privateAlan class ', privateMap.get(privateAlan));

最后一个假设支持 type="module"(92.5% 的浏览器)。它还具有使用 type="nomodule".

的后备支持