JavaScript Private Members

Source: Internet
Author: User
Tags closure export class

Class field declarations for JavaScript (a field declaration for JavaScript classes) has now entered Stage-3, which includes a focus for OOP developers: Private fields. JavaScript has never had a private member for no reason, so this proposal poses new challenges for JavaScript. But at the same time, JavaScript is already considering privatization at the time of ES2015 's release, so it is not without foundation to implement private members.

In the fourth chapter of the column "JavaScript full stack Engineer formation", the author discusses the key differences between prototype OOP and inheriting OOP. Here's a look at the problem with JavaScript private members today.

Keng

First dig a hole-this is a JS code, BusinessView in order to do two things, that is, the layout of forms and maps.

Represents the _ prefix convention as private

class BaseView {    layout() {        console.log("BaseView Layout");    }}class BusinessView extends BaseView  {    layout() {        super.layout();        this._layoutForm();        this._layoutMap();    }    _layoutForm() {        // ....    }    _layoutMap() {        // ....    }}

Then, due to the development of the business, there are many views that have a map layout. This is accomplished by inheriting, so the BusinessView map-related content is abstracted from a base class called MapView :

class MapView extends BaseView {    layout() {        super.layout();        this._layoutMap();    }    _layoutMap() {        console.log("MapView layout map");    }}class BusinessView extends MapView {    layout() {        super.layout();        this._layoutForm();        this._layoutMap();    }    _layoutForm() {        // ....    }    _layoutMap() {        console.log("BusinessView layout map");    }}

The above two pieces of code are very typical based on the idea of OOP, the intention is to expect all levels of the class can be layout() carried out at all levels should be responsible for the layout of the task. But there is always a gap between ideal and reality, and running in JavaScript will find that it BusinessView._layoutMap() was executed two times without MapView._layoutMap() execution. why not?

Virtual functions

In JavaScript, this method in the descendant class is called by default if the same name is defined in the ancestor and descendant classes. If you want to invoke a method of the same name in an ancestor class, you need to invoke it through the descendant class super. .

Here you can analyze the process:

When a subclass creates an object, its class and all ancestor class definitions are loaded. This time

    • CallBusinessView.layout()
    • Find super.layout() , start callingMapView.layout()
    • MapView.layout()Called inthis._layoutMap()
      • Then look for the current object ( BusinessView object)_layoutMap()
      • Find, call it

You see, because of the BusinessView definition _layoutMap , we don't even have to search the prototype chain. Right, this is the limitation of OOP based on the prototype relationship. If we look at the process of C #, we'll see a different

    • CallBusinessView.layout()
    • Find base.layout() , start callingMapView.layout()
    • MapView.layout()Called inthis._layoutMap()
      • MapViewfound in_layoutMap()
      • Check whether virtual functions
        • If yes, the last overloaded (override) function is found on the subclass, calling
        • If not, call directly

Did you find the difference? The key is to judge the "virtual function".

But what does this have to do with private members? Because private functions are definitely not virtual functions, in C #, if _layoutMap they are defined as private, then the MapView.layout() call must be MapView._layoutMap() .

The concept of virtual functions is a little complicated. It can be simply understood, however, that if a member method is declared as a virtual function, it will be called at the time it is called with its virtual function chain to find the last overload.

In JavaScript, although _ the contract prefix is private, it is only a gentleman's covenant, which is still not private in essence. The gentleman's covenant is effective to the person, the computer does not know you have this agreement .... However, if JavaScript really implements a private member, then the computer knows that it _layoutMap() is a private method and should invoke the definition in this class instead of looking for the definition in the subclass.

Solving the current privatization problem

JavaScript does not have a private member at the moment, but we need to solve the problem of private members effectively. Of course there are ways to use Symbol and closure to solve.

Note that the closure here is not a guide to generating closures in function functions, keep looking down

First, let's make it clear that we have a flexible view of the privatization issue--that is, the ancestor class caller does not go to the subclass to find it first when invoking a method. This problem can not be solved syntactically, JavaScript is to from the concrete instance from the back to the search for the specified name method. But what if the method name is not found?

It can be found because the method name is a string. A string represents the same meaning within the global scope. But ES2015 brought Symbol it, it had to be instantiated, and each instantiation must represent a different identity--if we define the class in a closure, declare one in the closure, Symbol use it as the name of the private member, the problem is solved, such as

const MapView = (() => {    const _layoutMap = Symbol();    return class MapView extends BaseView {        layout() {            super.layout();            this[_layoutMap]();        }        [_layoutMap]() {            console.log("MapView layout map");        }    }})();const BusinessView = (() => {    const _layoutForm = Symbol();    const _layoutMap = Symbol();    return class BusinessView extends MapView {        layout() {            super.layout();            this[_layoutForm]();            this[_layoutMap]();        }        [_layoutForm]() {            // ....        }        [_layoutMap]() {            console.log("BusinessView layout map");        }    }})();

Modern module-based definitions, even closures, can be saved (the module system automatically closes the scope)

const _layoutMap = Symbol();export class MapView extends BaseView {    layout() {        super.layout();        this[_layoutMap]();    }    [_layoutMap]() {        console.log("MapView layout map");    }}
const _layoutForm = Symbol();const _layoutMap = Symbol();export class BusinessView extends MapView {    layout() {        super.layout();        this[_layoutForm]();        this[_layoutMap]();    }    [_layoutForm]() {        // ....    }    [_layoutMap]() {        console.log("BusinessView layout map");    }}

The post-reform code can be output as expected:

BaseView LayoutMapView layout mapBusinessView layout map
Postscript

The author has developed a series of thinking habits of analyzing and solving problems in the course of many years ' development, so it is often possible to quickly penetrate the phenomena to see the substantive problems to be solved, and to solve them based on the existing conditions. Indeed, Symbol one of the reasons for this is to solve the problem of privatization, but why and how it needs to be analyzed and thought out.

Learning can get people to solve the same problems, but thinking can help people solve similar problems. Readers are welcome to study the author's column, "JavaScript All-stack engineer in mind", and follow the author to think, analyze and solve some problems in the software development process.

JavaScript Private Members

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.