Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the ways to implement the private properties of JS

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly shows you "what are the ways to implement the private attributes of JS". The content is easy to understand and clear. I hope it can help you solve your doubts. Let me lead you to study and learn this article "what are the ways to implement the private attributes of JS?"

Class is a template for creating objects, consisting of a series of properties and methods that represent data and operations on the same concept.

Some properties and methods are external, but others only want to be used internally, that is, private, so how to achieve private properties and methods?

I don't know how you will achieve it. I've combed it out. I've used about six ways. Let's take a look at it respectively:

_ prop

The easiest way to distinguish between private and public is to add an underscore _ to distinguish it from the name.

For example:

Class Dong {constructor () {this._name = 'dong'; this._age = 20; this.friend =' guang';} hello () {return'I\ m'+ this._name +','+ this._age + 'years old';}} const dong = new Dong (); console.log (dong.hello ())

The Dong here has private attributes _ name, _ age, and public attributes friend.

But this method is only a naming convention, telling developers that this property and method is private and should not be called, but it is not mandatory after all, and it cannot be stopped if others want to use it.

However, this method is still used a lot, and has a long history.

So how can it be truly private based on this specification? Proxy is about to be used:

Proxy

Proxy can define the logic of get, set and Object.keys of the target object. You can make a judgment at this layer. If it starts with an underscore, you will not be allowed to access it, otherwise you can access it.

For example, it's the same class:

Class Dong {constructor () {this._name = 'dong'; this._age = 20; this.friend =' guang';} hello () {return'I\ m'+ this._name +','+ this._age + 'years old';}} const dong = new Dong ()

Instead of directly calling the property methods of its object, we first use a layer of Proxy to constrain the behavior of get, set, and getKeys:

Const dong = new Dong (); const handler = {get (target, prop) {if (prop.startsWith ('_')) {return;} return target [prop];}, set (target, prop, value) {if (prop.startsWith ('_')) {return;} target [prop] = value }, ownKeys (target, prop) {return Object.keys (target) .filter (key = >! key.startsWith ('_'))},} const proxy = new Proxy (dong, handler)

We define the handler of get, set, and ownKeys for dong through new Proxy:

Get: return empty if the underscore begins with _, otherwise return the attribute value of the target object target [prop]

Set: return directly at the beginning of the underscore _, otherwise set the attribute value of the target object

OwnKeys: when accessing keys, filter out the attributes at the beginning of the underscore in the target object and return

This results in the privatization of the attributes at the beginning of the underscore:

Let's test it:

Const proxy = new Proxy (dong, handler) for (const key of Object.keys (proxy)) {console.log (key, proxy [key])}

Indeed, only the methods of the public properties are printed here, and the two attributes at the beginning of the underscore are not printed.

We implement truly private attributes based on the naming convention of _ prop!

Try calling the method again:

Why is it undefined?

Because the this of the proxy.hello method also points to proxy and will be restricted, you need to do the following:

If you are using a method, bind it to this as the target object.

This allows the hello method to access the private properties that begin with _:

We implement truly private attributes through Proxy for underlined naming conventions, but it's troublesome to define a layer of Proxy. Is there a way not to define Prxoy?

There are, for example, Symbol:

Symbol

Symbol is an api added by es2015 to create unique values. Based on this unique feature, we can implement private properties.

Like this:

Const nameSymbol = Symbol ('name'); const ageSymbol = Symbol (' age'); class Dong {constructor () {this [nameSymbol] = 'dong'; this [ageSymbol] = 20;} hello () {return I\' m'+ this [nameSymbol] +','+ this [ageSymbol] + 'years old';}} const dong = new Dong ()

Instead of using name and age as private property names, we use Symbol to generate unique values as names.

In this way, because you can't get the attribute name, you can't get the corresponding attribute value:

This approach is simpler than the Proxy approach and is one of the many ways to implement private properties.

If you want to expose, you can define a get method:

But is this private property really inaccessible?

No, there is an api called Object.getOwnPropertySymbols, which can take all the Symbols properties of the object, and then get the property value:

So it's just that Object.keys can't get the corresponding attributes, and it's not as perfect as Proxy.

Is there a better way to do without Proxy than to have Symbol?

Then you can try this:

WeakMap

You can access properties and methods outside because we hang it on this, so you can't access it if you don't hang it on this.

For example, use a Map to save private properties:

Const privateFields = new Map (); class Dong {constructor () {privateFields.set ('name',' dong'); privateFields.set ('age', 20);} hello () {return'i\' m'+ privateFields.get ('name') +','+ privateFields.get ('name') +' years old';}}

Let's test it:

This seems to be possible, but I don't know if you have found the problem:

All objects use the same Map and interact with each other

The Map still exists after the object is destroyed.

How to solve this problem?

I do not know if you have used WeakMap, its characteristic is that you can only use the object as a key, the object is destroyed, and the key-value pair is destroyed.

The above two problems are solved perfectly:

Because objects are used as key, different objects are placed on different key-value pairs and have no influence on each other.

When the object is destroyed, the corresponding key-value pair is destroyed without manual management.

It seems to be perfect, let's achieve the following:

Const dongName = new WeakMap (); const dongAge = new WeakMap (); const classPrivateFieldSet = function (receiver, state, value) {state.set (receiver, value);} const classPrivateFieldGet = function (receiver, state) {return state.get (receiver);} class Dong {constructor () {dongName.set (this, void 0); dongAge.set (this, void 0); classPrivateFieldSet (this, dongName, 'dong'); classPrivateFieldSet (this, dongAge, 20) } hello () {return'I\ 'm'+ classPrivateFieldGet (this, dongName) +','+ classPrivateFieldGet (this, dongAge) + 'years old';}}

Each property defines a WeakMap to maintain, key is the current object, and the value is the property value. Get and set use classPrivateFieldSet and classPrivateFieldGet methods, which are finally accessed from WeakMap.

Initialize the property value of the current object in the constructor, that is, dongName.set (this, void 0), where the return value of void 0 is undefined, which means.

Test:

Wow, private attributes can also be achieved through WeakMap!

But there is no need to define classPrivateFieldGet here, isn't it just xxMap.get?

Indeed, the purpose of the package layer is to add some extra logic, which can also be taken directly from weakMap.

But it is also very troublesome to write in this way. is there an easier way?

Can you design a syntax sugar that automatically compiles in this way?

You're right, there is this grammatical sugar:

# prop

There is now a draft es for private attributes that can identify private properties and methods in the form of #.

Like this:

Class Dong {constructor () {this.#name = 'dong'; this.#age = 20; this.friend =' guang';} hello () {return'i\ m'+ this.#name + this.#age + 'years old';}

Here name and age are private, while friend is public.

This new syntax JS engine doesn't support it that fast, but it can be used in advance by compiling to a lower version of the syntax by babel or ts compilers.

For example, babel has a plug-in for @ babel/proposal-private-property-in-object, which can compile this syntax:

Babel is implemented by compiling # prop into the above WeakMap.

This plug-in is automatically introduced in the @ babel/preset-env default:

You can also use this syntax directly in addition to babel,ts:

It is also implemented by compiling it to WeakMap.

In fact, there are quite a few new grammars implemented by ts, such as? And?? The syntax of the optional chain and the default value, respectively, are equivalent in the following two ways:

Const res = data?.name? 'dong';const res2 = data & & data.name | |' dong'

This new syntax is available directly, and you need to introduce the proposal plug-in for babel.

By the way, I remember that class also has a private modifier in ts. Isn't that also a private attribute?

It's actually private, but it's not exactly. Let's take a look:

Ts private

Ts can modify the visibility of properties and methods through private:

Private indicates that the attribute is private and can only be accessed internally by class.

Protected means protection, and only class and sub-class can access

Public means public, and can be accessed externally.

There is a difference between type checking and prompting, for example, the private property is not accessible outside of class:

Class can be accessed internally:

But this constraint is only used for type checking, only during compilation, and there is no such constraint at run time.

We can look at the compiled code:

You can see that no processing has been done.

If you use the method of # prop, in addition to being private at compile time, the runtime is also:

So, if you want to implement a real private, you can use the # prop way, and if it's just a compile-time constraint, just declare private.

Summary

Class is used to define a series of properties and methods around a concept, either internally or externally. Only the properties and methods used internally need to be privatized.

I have set up six ways to implement the private attribute method:

Distinguish from naming by underscore _ prop

Define the logic of get, set and ownKeys through Proxy

Unique attribute names are defined through Symbol and cannot be obtained through keys

Save the private properties and methods of all objects through WeakMap

Proprietary through # prop's new es syntax, babel and tsc will compile them into WeakMap

Compile-time constraints through the private of ts

Of these six ways, three are only pseudo-private, such as _ prop (still accessible), ts's private (accessible at run time), and Symbol (which can be accessed by symbol through Object.getOwnSymbols).

The other three are truly private, including Proxy, WeakMap, and # prop (currently compiled to WeakMap).

There are some ways to find ways from attribute names, such as _ prop and Symbol, some from this, such as Proxy (package layer) and WeakMap (not linked to this), and some from the language itself, such as ts's private or es's new syntax # prop.

The above is all the contents of the article "what are the ways to implement the private properties of JS". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report