Heim  >  Artikel  >  Web-Frontend  >  Umfassende Analyse privater Mitglieder in js (mit Code)

Umfassende Analyse privater Mitglieder in js (mit Code)

不言
不言Original
2018-08-14 11:09:521938Durchsuche

Dieser Artikel bietet Ihnen eine umfassende Analyse privater Mitglieder in js (mit Code). Ich hoffe, dass er für Freunde in Not hilfreich ist.

Klassenfelddeklarationen für JavaScript (Felddeklarationen von JavaScript-Klassen) sind jetzt in Stufe 3 eingetreten, die ein Element enthält, das OOP-Entwicklern große Sorgen bereitet: Private Felder. Nicht umsonst hatte JavaScript nie private Mitglieder, daher bringt dieser Vorschlag neue Herausforderungen für JavaScript mit sich. Gleichzeitig dachte JavaScript jedoch bereits bei der Veröffentlichung von ES2015 über die Frage der Privatisierung nach, sodass die Implementierung privater Mitglieder nicht ohne Grundlage ist.

Gruben

Graben Sie zuerst eine Grube - das ist ein Teil des JS-Codes. BusinessView muss zwei Dinge tun, nämlich das Layout des Formulars und die Karte.

Stellt das Präfix _ als privates
class BaseView {
    layout() {
        console.log("BaseView Layout");
    }
}

class BusinessView extends BaseView  {
    layout() {
        super.layout();
        this._layoutForm();
        this._layoutMap();
    }

    _layoutForm() {
        // ....
    }

    _layoutMap() {
        // ....
    }
}
dar

Dann wurde aufgrund der Geschäftsentwicklung festgestellt, dass viele Ansichten Kartenlayouts haben. Zur Implementierung wird hier die Vererbungsmethode verwendet, sodass der kartenbezogene Inhalt von BusinessView in eine Basisklasse namens MapView abstrahiert wird:

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");
    }
}

Die beiden oben genannten Codeteile basieren auf sehr typischen OOP-Ideen Bei der Vererbung besteht die ursprüngliche Absicht darin, zu erwarten, dass Klassen auf jeder Ebene layout() verwenden können, um Layoutaufgaben auszuführen, für die jede Ebene verantwortlich sein sollte. Aber es gibt immer eine Lücke zwischen Ideal und Realität. Wenn Sie es in JavaScript ausführen, werden Sie feststellen, dass BusinessView._layoutMap() zweimal ausgeführt wird, während MapView._layoutMap() nicht ausgeführt wird. Warum?

Virtuelle Funktion

Wenn in JavaScript eine Methode mit demselben Namen in der Vorfahren- und Nachkommenklasse definiert ist, wird diese Methode in der Nachkommenklasse standardmäßig aufgerufen. Wenn Sie die gleichnamige Methode in der Vorfahrenklasse aufrufen möchten, müssen Sie sie über super. in der Nachkommenklasse aufrufen.

Hier können Sie diesen Prozess analysieren:

Wenn eine Unterklasse ein Objekt erstellt, wurden die Definitionen ihrer Klasse und aller Vorgängerklassen geladen. Zu diesem Zeitpunkt ruft

  • BusinessView.layout()

  • auf, um super.layout() zu finden und MapView.layout()

  • MapView.layout()this._layoutMap()

    in 🎜>
      auf und suchen Sie dann nach
    • BusinessView_layoutMap() Objekt) > Finden Sie es und nennen Sie es

    • Sie sehen, da
definiert, wird die Prototypenkette überhaupt nicht durchsucht. Ja, dies ist eine Einschränkung von OOP, die auf Prototypbeziehungen basiert. Wenn wir uns den Verarbeitungsprozess von C# ansehen, werden wir feststellen, dass es anders ist

BusinessView_layoutMap

Aufruf
  • BusinessView.layout()

    Suchen
  • und Beginnen Sie mit dem Aufruf
  • base.layout()MapView.layout()

  • wird in
  • MapView.layout()this._layoutMap()

  • aufgerufen. Wenn ja, gehen Sie zur Unterklasse, um sie zu finden Rufen Sie für die letzte Überlastungsfunktion (Override)
    • auf. Wenn nicht, rufen Sie direkt
    • auf und suchen Sie
    • MapView 🎜>_layoutMap()Überprüfen Sie, ob die virtuelle Funktion funktioniert

    • Haben Sie den Unterschied bemerkt? Der Schlüssel besteht darin, die „virtuelle Funktion“ zu bestimmen.
    Aber was hat das mit privaten Mitgliedern zu tun? Da private Funktionen definitiv keine virtuellen Funktionen sind, muss
in C#

aufrufen, wenn

als privat definiert ist.

_layoutMapDas Konzept der virtuellen Funktionen ist etwas kompliziert. Es kann jedoch einfach verstanden werden, dass eine Mitgliedsmethode, wenn sie als virtuelle Funktion deklariert wird, beim Aufruf ihrer virtuellen Funktionskette folgt, um die letzte aufzurufende Überladung zu finden. MapView.layout()MapView._layoutMap()Obwohl das

-Präfix in JavaScript als privat gilt, handelt es sich lediglich um eine Gentlemen's Agreement und ist immer noch nicht privater Natur. Ein Gentleman's Agreement gilt für Menschen, aber der Computer weiß nicht, dass Sie dieses Abkommen haben ... Wenn JavaScript jedoch tatsächlich private Mitglieder implementiert, weiß der Computer, dass
eine private Methode ist und die Definition in dieser Klasse aufrufen sollte, anstatt in der Unterklasse nach der Definition zu suchen.

Lösen Sie das aktuelle Privatisierungsproblem__layoutMap()JavaScript hat derzeit keine privaten Mitglieder, aber wir müssen das Problem der privaten Mitglieder schnell und effektiv lösen. Was sollen wir tun? Natürlich gibt es eine Möglichkeit, das Problem zu lösen, indem man

und Verschlüsse verwendet.

Beachten Sie, dass der Abschluss hier kein Leitfaden zum Generieren eines Abschlusses in einer Funktion ist. Bitte lesen Sie weiter

SymbolZunächst möchten wir klarstellen, dass wir uns mit diesem Privatisierungsproblem in einem befassen werden Flexibler Weg - das heißt, lassen Sie die Vorfahren Wenn ein Klassenaufrufer eine Methode aufruft, sucht er nicht zuerst in der Unterklasse. Dieses Problem kann grammatikalisch nicht gelöst werden. JavaScript muss nach der Methode suchen, den Namen von der spezifischen Instanz aus rückwärts anzugeben. Was aber, wenn der Methodenname nicht gefunden werden kann?

之所以能找到,因为方法名是字符串。一个字符串在全局作用域内都表示着同样的意义。但是 ES2015 带来了 Symbol,它必须实例化,而且每次实例化出来一定代表着不同的标识 —— 如果我们将类定义在一个闭包中,在这个闭包中声明一个 Symbol,用它来作为私有成员的名称,问题就解决了,比如

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");
        }
    }
})();

而现代基于模块的定义,甚至连闭包都可以省了(模块系统会自动封闭作用域)

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");
    }
}

改革过后的代码就可以按预期输出了:

BaseView Layout
MapView layout map
BusinessView layout map

相关推荐:

js中对执行上下文以及变量对象的解析

js中字符方法以及字符串操作方法的总结(附代码)

Das obige ist der detaillierte Inhalt vonUmfassende Analyse privater Mitglieder in js (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn