在ES5中,您可以使用这样的私有和公共变量来模拟一个类:
car.js
function Car() {
// using var causes speed to be only available inside Car (private)
var speed = 10;
// public variable - still accessible outside Car
this.model = "Batmobile";
// public method
this.init = function(){
}
}
但是在ES6中,你不能再在构造函数之外声明变量了,这使得它实际上更难以以OOP方式使用类!
您可以使用此方法在构造函数中声明变量,但这会使它们默认公开。这非常奇怪,因为ES6 DOES 有一个get / set关键字!
class Vehicle {
constructor(make, year) {
// the underscore is nice, but these are still public!
this._make = make;
this._year = year;
}
// get and set can be handy, but would make more sense
// if _make and _year were not accessible any other way!
get make() {
return this._make;
}
get year() {
return this._year;
}
}
答案 0 :(得分:6)
ES6标准没有提供一种定义私有变量的新方法。
事实上,新的ES6 类只是围绕常规基于原型的构造函数的语法糖。
获取和 set 关键字为ES5自定义getter和setter的简化定义提供了一种方法,这些getter和setter之前使用Object.defineProperty()
您可以做的最好的事情就是将这些技巧与Symbols或WeakMaps
一起使用以下示例介绍如何使用WeakMap存储私有属性。
// myModule.js
const first_name = new WeakMap();
class myClass {
constructor (firstName) {
first_name.set(this, firstName);
}
get name() {
return first_name.get(this);
}
}
export default myClass;
我指的是David Vujic What? Wait. Really? Oh no! (a post about ES6 classes and privacy)撰写的关于使用WeakMaps的文章。
答案 1 :(得分:3)
与ES5相同:定义必须访问构造函数中的私有变量而不是原型的方法,从而使它们成为特权方法。
否则,没有好的方法允许原型方法访问私有数据,但仍然可以从外部隐藏它。您可以尝试符号,弱图或握手,但IMO没有一个是完美的。有关一些想法,请参阅accessing private member variables from prototype-defined functions。
答案 2 :(得分:3)
但是在ES6中,你不能再在构造函数之外声明变量
你并不需要。您也没有在ES5构造函数中执行此操作。您可以将代码逐字翻译为
class Car {
constructor() {
// local variable
var speed = 10;
// public property
this.model = "Batmobile";
// public method
this.init = () => {
…
}; // using an arrow function here simplifies things
}
}
答案 3 :(得分:2)
2016年1月更新 - 虽然我发现接受的答案中给出的方法是正确的,但我想说明在ES2015 +中使用模块和符号是一种有效的信息隐藏技术(但是类使用符号的属性将被隐藏,而不是严格保密。
通过ES2015 模块(只能导出您声明为导出的内容)和ES2015 symbols的组合,可以实现有效,轻量级的信息隐藏。 符号是一种新的内置类型。每个新的Symbol值都是唯一的。因此可以用作对象的键。
如果客户端调用代码不知道用于访问该密钥的符号,则由于未导出该符号,因此无法获取该密钥。
使用代码的快速示例:
<强> vehicle.js 强>
const s_make = Symbol();
const s_year = Symbol();
export class Vehicle {
constructor(make, year) {
this[s_make] = make;
this[s_year] = year;
}
get make() {
return this[s_make];
}
get year() {
return this[s_year];
}
}
并使用模块vehicle.js
<强> client.js 强>
import {Vehicle} from './vehicle';
const vehicle1 = new Vehicle('Ford', 2015);
console.log(vehicle1.make); //Ford
console.log(vehicle1.year); // 2015
然而,符号虽然是唯一的,但实际上并不是私有的,因为它们是通过Object.getOwnPropertySymbols等反射功能公开的......
const vals = Object.getOwnPropertySymbols(vehicle1);
vehicle1[vals[0]] = 'Volkswagon';
vehicle1[vals[1]] = 2013;
console.log(vehicle1.make); // Volkswagon
console.log(vehicle1.year); // 2013
外卖消息 - 模块通常是一种隐藏内容的好方法,因为如果不导出然后无法在模块外部使用,并且与私有存储的符号一起用作键,那么类属性也可能被隐藏(但是不一定是私人的)。当被认为是构建良好的模块(amd,commonjs或es6 / 2015)的一部分时,类声明特别适合。