在 ES2020 中引入了私有字段 (Private Fields) 的语法,可以通过在字段名前添加 # 来声明私有字段。私有字段是只能在类内部访问的字段,对外部不可见,可以起到隐藏实现细节的作用。
使用 # 符号声明是 ES6 中官方提供的用于声明私有属性的方式,可以被广泛使用,但是在某些情况下可能需要进行编译才能使用。
使用下划线 _ 开头的命名方式,是一种普遍的约定,被广泛使用来表示某个属性是私有属性,但是在语言层面上并没有真正的私有属性的保护。因此,如果在项目中使用下划线作为私有属性的命名方式,需要在文档中明确说明,以避免其他开发人员错误地修改了这些属性。
如果两者同时出现的化一般 _ 通常用来标识受保护的属性和方法,而 # 用来标识真正的私有属性和方法。
下面是一个使用 # 定义私有字段的示例:
class MyClass {
#privateField = 'private';
#privateMethod() {
console.log('This is a private method.');
}
publicMethod() {
console.log('This is a public method.');
console.log(this.#privateField);
this.#privateMethod();
}
}
const myObj = new MyClass();
myObj.publicMethod();
console.log(myObj.#privateField); // SyntaxError: Private field '#privateField' must be declared in an enclosing class
myObj.#privateMethod(); // SyntaxError: Private field '#privateMethod' must be declared in an enclosing class
上面的代码转换为es5
使用 # 定义的方法和属性是ES6的语法,无法直接转换成ES5,需要使用Babel等工具进行转换。转换后的代码中可能使用闭包等方式来实现类似的私有属性和方法的隐藏。以下是一个可能的转换结果
"use strict";
function MyClass() {
var _privateData = new WeakMap();
function _privateMethod() {
console.log("This is a private method.");
}
this.publicMethod = function () {
console.log("This is a public method.");
};
_privateData.set(this, {
privateProperty: "This is a private property.",
});
}
是的, # 号的实现机制实际上也是利用了 WeakMap 来存储私有属性和方法。在JavaScript引擎内部,私有属性和方法的实现方式可能是通过使用一些内置的标记(如 Symbol )和特殊的数据结构(如 WeakMap )来实现的,而这些内部实现细节对于JavaScript程序员来说是不可见的。因此,尽管 # 号的语法更加简洁明了,但它本质上还是使用了类似于 WeakMap 的机制来实现私有属性和方法的封装。
使用‘#’和使用WeakMap的实现机制不同,但它们的主要区别是语法上的。使用#更加简单明了,并且可以直接在类内部使用,而WeakMap需要在类外部定义,并且需要在类内部创建WeakMap对象进行维护。
从性能上来说,两者的差别并不是很大,#底层实现使用了WeakMap来维护私有属性,因此使用#和使用WeakMap的性能差别可以忽略不计。
总体来说,使用 # 来定义私有属性更加简洁易懂,并且可以直接在类内部使用,是一个更好的选择。而使用WeakMap的方式则更加灵活,可以在不同的类中复用同一个WeakMap对象,但需要在类外部定义和创建WeakMap对象,相对来说略显繁琐。
Symbol和WeakMap都是用于实现私有属性的方式,不同的是Symbol是一种数据类型,而WeakMap是一种数据结构。
Symbol是一种基本数据类型,可以用来生成唯一的值。它的主要作用是用作对象属性名的标识符,因为Symbol类型的值是唯一的,所以可以防止属性名冲突。在类中使用Symbol可以实现私有变量和方法的定义。
WeakMap是ES6中新增的数据结构,它可以实现键值对的存储,并且键只能是对象,值可以是任意类型的值。WeakMap的特点是:1.键值对的键只能是对象,不能是其他类型的值;2.键是弱引用的,即只要键所引用的对象在垃圾回收时被回收了,键值对也会被自动删除。
下面是使用Symbol和WeakMap来定义私有变量和方法的示例:
使用Symbol:
const privateData = Symbol('privateData');
class MyClass {
constructor(data) {
this[privateData] = data;
}
getData() {
return this[privateData];
}
#privateMethod() {
console.log('This is a private method.');
}
publicMethod() {
console.log('This is a public method.');
this.#privateMethod();
}
}
const myObject = new MyClass('private data');
console.log(myObject.getData()); // 'private data'
myObject.publicMethod(); // This is a public method. This is a private method.
console.log(myObject.privateData); // undefined
使用WeakMap:
const privateData = new WeakMap();
class MyClass {
constructor(data) {
privateData.set(this, data);
}
getData() {
return privateData.get(this);
}
getPrivateData() {
return privateData;
}
getPrivateMethod() {
return privateData.get(this).privateMethod;
}
setPrivateMethod(func) {
const data = privateData.get(this);
data.privateMethod = func;
privateData.set(this, data);
}
}
const myObject = new MyClass({ privateData: 'private data' });
myObject.setPrivateMethod(function() {
console.log('This is a private method.');
});
console.log(myObject.getData()); // { privateData: 'private data', privateMethod: [Function] }
console.log(myObject.getPrivateData()); // WeakMap { }
console.log(myObject.getPrivateMethod()); // [Function]
本文由 chat gpt 整理而来
官网地址:https://chat.openai.com