How to realize the grammatical features of private members and the realization of private members based on JavaScript _javascript skills

Source: Internet
Author: User
Tags closure naming convention

Objective

Encapsulation is an essential concept in object-oriented programming paradigm, and in traditional object-oriented languages such as java,c++, private members are an important way to implement encapsulation. But in JavaScript, it is not in the grammatical characteristics of the private members to provide support, which also allows developers to use a variety of Chine to achieve the private members of JS, the following will introduce the current implementation of JS Private member characteristics of several schemes and their advantages and disadvantages of comparison.

Some of the existing implementation scenarios

Contract naming scheme

A member whose name begins with an underscore ' _ ' is a private member, allowing only class member methods to access the call, and no private members outside. The simple code is as follows:

Javascript

var MyClass = function () {
  this._privateprop = ' Privateprop ';
};
MyClass.prototype.getPrivateProp = function () {return
  this._privateprop;
};
var my = new MyClass ();
Alert (My.getprivateprop ()); ' Privateprop ';
alert (My._privateprop); is not really hidden, still pops up ' Privateprop '

Advantages

There is no doubt that the Convention naming is the simplest of private member implementations, with no work at the code level.
Easy to debug, can directly see the object on the console private members, easy to troubleshoot problems.
Good compatibility, ie6+ support

Insufficient

There is no way to prevent external access and changes to private members, and there is nothing you can do if a developer who does not know or does not comply with the convention changes private properties.
You have to force or convince everyone to follow this convention, and of course this is not too much of a problem in a code-compliant team.

ES6 symbol Scheme

In Es6, an attribute of Symbol is introduced, which is introduced for the purpose of implementing private members.
The main idea is that for each private member of the name generated a random and unique string key, the key is not visible externally, internal visibility is through the JS closure variable implementation, sample code is as follows:

Javascript

(function () {
   var privateprop = Symbol ();//each invocation produces a unique key
   function MyClass () {
     This[privateprop] = ' Privateprop '; The closure is referenced to this key
   }
   MyClass.prototype.getPrivateProp = function () {return
     this[privateprop];
   };
} ();
var my = new MyClass ();
Alert (My.getprivateprop ()); ' Privateprop ';
alert (My.privateprop); Pop-up undefined because the member's key is actually a random string

Advantages

To make up for the defects of the naming convention scheme, the external access rights of private members cannot be obtained by the normal way.
The ease of debugging is acceptable, typically by passing a string parameter to the constructor of symbol, and the corresponding private property name on the console is displayed as: symbol (key)

Compatibility is good, browsers that do not support symbol can easily be shim out.

Insufficient

A bit awkward in writing, you must create a closure variable for each private member so that internal methods can be accessed.
Externally, you can obtain the name of the symbol property of an instance by Object.getownpropertysymbols, and gain access to private members by that name. This scenario appears to be relatively small, and the level of developers who know this approach is believed to have enough ability to know what the impact of their actions will be, so the shortfall is not really a problem.

ES6 Weakmap Scheme

In Es6, the introduction of MAP, Weakmap container, the biggest feature is that the container's key name can be arbitrary data types, although not intended to implement private member introduction, but unexpectedly can be used to implement private member characteristics.

The main idea is to create a Weakmap container at the class level that stores the private members of each instance, which is not visible externally and is visible internally through the closure; The internal method gets the private members of the corresponding instance on the container by using the instance as the key name, as the sample code reads:

Javascript

(function () {
   var privatestore = new Weakmap ();//Private Member Storage container
   function MyClass () {
     privatestore.set () Privateprop: ' Privateprop '}); Within the closure reference to Privatestore, with the current instance of the key, set private member
   }
   MyClass.prototype.getPrivateProp = function () {return
     Privatestore.get (this). Privateprop; 
   }
();
var my = new MyClass ();
Alert (My.getprivateprop ()); ' Privateprop ';
alert (My.privateprop); Pop-up undefined, no Privateprop property on instance

Advantages

To make up for the defects of the naming convention scheme, the external access rights of private members cannot be obtained by the normal way.
For Weakmap to do some encapsulation, pull out a private feature of the implementation module, can be written on the relative Symbol scheme more concise and clean, one of the encapsulation of the implementation can view reference article 3.
The last one is a personal view of the greatest advantage: based on the WEAKMAP scheme, it is easy to implement the protection of member characteristics (this topic will be mentioned in other articles:))

Insufficient

Bad debugging, because private members are inside the closure container, unable to view the corresponding private member in the console print instance
To confirm performance issues, according to ES6 's related mailing list, Weakmap seems to be in order one by one contrast to locate the key, the time complexity of O (n), and the hash algorithm O (1) is much slower than

The biggest flaw is the memory inflation problem associated with compatibility, which cannot be implemented in browsers that do not support weakmap, so instances cannot be garbage collected. For example, in the sample code Privateprop is a very large data item, without weak references, the instance cannot be recycled, resulting in memory leaks.

Summary of existing implementation scenarios

From the above comparison, the maximum advantage of the symbol scheme is that it is easy to simulate the implementation, while the advantage of the WEAKMAP is the ability to achieve protection of members, at this stage, the unbearable problem is unable to simulate the implementation of weak reference features caused by memory problems. So my thinking turns to the direction of combining the two advantages.

The integration scheme of Symbol + class Weakmap

The biggest problem in the WEAKMAP scheme is the inability to shim weak references, which is less convenient for debugging.

Shim out of the weakmap is primarily unable to trace the life cycle of the instance, while the life cycle of the private member on the instance is dependent on the instance, so it is better to put the private member portion of the instance level on the instance? The instance is gone, and nature's properties are destroyed. A private storage area can be hidden by using Symol.

The scheme provides a createprivate function that returns a private token function, which is not externally visible, is obtained internally through the closure function, and the current instance returns the private storage area of the current instance. The use of the following methods:

Javascript

(function () {
   var $private = createprivate ();//Private Member token function, which can pass in object arguments and act as a private member of the prototype chain
   MyClass () {
     $ Private (this). Privateprop = ' Privateprop '; Within the closure reference to Privatestore, with the current instance of the key, set private member
   }
   MyClass.prototype.getPrivateProp = function () {return
     $ Private (this). Privateprop;}
();
var my = new MyClass ();
Alert (My.getprivateprop ()); ' Privateprop ';
alert (My.privateprop); Pop-up undefined, no Privateprop property on instance

The main code is to implement the Createprivate function, the approximate implementation is as follows:

Javascript

Createprivate.js
function Createprivate (prototype) {
  var privatestore = Symbol (' Privatestore ');
  var classtoken = Symbol (' Classtoken ');
  return function Getprivate (instance) {
     if (!instance.hasownproperty (Privatestore)) {
       Instance[privatestore] = {};
     }
    var store = Instance[classtoken];
     Store[token] = Store[token] | | Object.create (Prototype | | {});
     return Store[token];}

The above implementation has done two-tier storage, Privatestore this layer is the unified Private member storage area of the instance, while the classtoken corresponds to the different private member definitions between the inheritance levels, the base class has the private member area of the base class, and the private member region of the base class differs.

Of course, only one layer of storage can be implemented, two tiers of storage is only for debugging convenience, you can directly in the console through the symbol (' Privatestore ') This property to view the private part of each level of the instance.

ES5 Property Getter interception scheme for exotic flowers

The scheme is purely idle play, mainly using the ES5 provided by the getter, according to Argument.callee.caller to judge the call scene, if it is external then throw an exception or return undefined, if it is internal call then return true private members, It is more complex to implement and does not support strict mode, and is not recommended for use. Interested students can see the realization.

Summarize

Compared with the above schemes, I personally tend to symbol+weakmap integration scheme, combining the advantages of both, and make up for the Weakmap and Symbol writing redundancy. Of course, I believe that with the development of JS, private members and protection members will sooner or later on the grammar level support, just as ES6 to the Class keyword and super syntactic sugar support, only at this stage requires developers to use some skills to fill the gaps in language characteristics.

How JavaScript private members are implemented

Generally speaking, this book is still possible, but after reading this book still left a few problems have been bothering me, such as JS private variable implementation, prototype, and so on, after their own series of tests, and now finally figured out.

A lot of books are saying that JavaScript is not really implementing JavaScript private members, so at the time of development, the Unified Convention __ Two underscore start as a private variable.

Later, the feature of the closure in JavaScript was discovered, which completely solved the problem of JavaScript private members.

 function Testfn () { 
    var _name;//defines JavaScript private member 
    This.setname = function (Name) { 
     _name = Name; _name 
    } 
    this.getname = function () {return 
     _name; 
    } 
} End TESTFN 
var test = TESTFN (); 
Alert (typeof Test._name = = "undefined")//true 

Test._name cannot be accessed at all, but can be accessed using object methods because closures can fetch information from the current execution environment.

Next, let's see how the shared members are implemented.

function Testfn (name) {this 
  . name = name; 
  This.getname = function () {return this 
   . Name; 
  } 
} 
var test = new Testfn ("Kenchen"); 
Test.getname (); Kenchen 
test. Name = "CC"; 
Est.getname ();//cc 

Next, let's look at how the class static variable is implemented.

function Testfn () { 
} 
testfn.name = "Kenchen"; 
alert (testfn.name);//kenchen 
testfn.name = "CC"; 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.