js 学習ノート: class、super、extends キーワード

js 学習ノート: class、super、extends キーワード

序文

JavaScript 言語は ES6 でキーワード class を導入しました。面接では、面接官から ES6 の class についての理解、コード内でのこのキーワードの使い方、このキーワードを使用する際の注意点について質問されることがよくあります。この記事では、関連する知識のポイントをまとめます。

文章

1. es6の前にオブジェクトを作成する

まず、es6 より前では、オブジェクトを作成する場合、各インスタンスがメソッドを呼び出せるように、プロトタイプに静的メソッドを追加して、コンストラクター関数を通じてのみオブジェクトを作成できたという事実を見てみましょう。

関数 Person(名前, 年齢) {
            this.name = 名前
            this.age = 年齢
            Person.prototype.sayHello = 関数 () {
                「hello,」+ this.name + 「おはようございます」を返します
            }
        }
        person = new Person("セレンディピティ", 18) とします。
        console.log(person.sayHello())//こんにちは、セレンディピティ、おはようございますconsole.log(person instanceof Person);//true
        console.log(person インスタンスオブオブジェクト);//true

2. es6 後のクラス宣言

クラスはオブジェクトを作成するためのテンプレートであり、データを操作するためのコードでデータをカプセル化します。 js のクラスはプロトタイプの上に構築されますが、ES5 クラスに似た構文とセマンティクスもいくつか共有します。

実際、クラスは特別な種類の関数です。関数宣言と関数式の定義と同様に、クラス構文もクラス宣言とクラス式の 2 つの部分で構成されます。

クラス Person {
            コンストラクター(name, age) { //独自のプロパティ。このプロパティはインスタンス上に表示され、クラスのコンストラクターまたはメソッドでのみ作成できます。this.name = name
                this.age = 年齢
            }
            sayHello(){//Perosn.prototype.sayHello と同等
                `hello,${this.name},おはようございます` を返します
            }
        }
        person = new Person("セレンディピティ", 18) とします。
        console.log(person.sayHello()); //こんにちは、セレンディピティ、おはようございます console.log(person instanceof Person); //true
        console.log(person インスタンスオブオブジェクト);//true
        console.log(typeof Person);//関数
        console.log(typeof Person.prototype.sayHello);//関数

クラス宣言を使用すると、コンストラクターとして使用する特別な構築メソッドを定義しなくても、クラス内のコンストラクター メソッドを使用してコンストラクターを定義できます。

クラスの構文は ES5 以前の通常の関数の構文と似ていますが、注意すべき機能がいくつかあります。

(1)クラス宣言はホイストされません。クラス宣言の動作はletに似ているため、実行中にクラス内に一時的なデッドゾーンが発生します。

(2)クラス内のすべてのコードは自動的に厳密モードで実行され、厳密モードを終了することはできない。

(3)クラス内のすべてのメソッドは非列挙型です。通常のカスタムメソッドは、object.defineProperty()を通じてのみ非列挙型として定義できます。

(4) クラス内のメソッドには[[construct]]が含まれていないため、newで呼び出すとエラーが発生します。

(5)newを使わずにクラスコンストラクタを呼び出すとエラーが発生する

(6)クラスメソッド内でクラス名をオーバーライドしようとするとエラーが発生します。

上記のコードを次のように ES5 に変換します。

PersonClass = (関数() {
            「厳密な使用」
            const PersonClass = 関数 (名前、年齢) {
                // コンストラクタがnewによって呼び出されるかどうかを判定する if (typeof new.target === "undefined") {
                    throw new Error("コンストラクタは new で呼び出す必要があります。")
                }
                this.name = 名前
                this.age = 年齢
            }
            Object.defineProperty(PersonClass.prototype, "sayHello", {
                値: 関数 () {
                    if (typeof new.target !== "undefined") { // 呼び出し時にnewが使用されていないことを確認する
                        throw new Error("メソッドは new では呼び出せません。")
                    }
                    「hello,」+ this.name + 「おはようございます!」を返します。
                },
                列挙可能: false、
                設定可能: true、
                書き込み可能: true
            })
            PersonClassを返す
        })()
        var personClass = 新しい PersonClass("セレンディピティ", 18)
        console.log(personClass.name);//セレンディピティ
        console.log(personClass.sayHello()); ///こんにちは、セレンディピティ、おはようございます!

2 つの PersonClass 宣言、つまり外側のスコープ内の let 宣言と、すぐに実行される関数内の const 宣言があるため、クラス メソッドはクラス名をオーバーライドできませんが、クラス外のコードは許可されます。同時に、クラス内のクラス名のみが const として宣言されていると見なされるため、クラス名を外部で書き換えることはできますが (let と同等)、クラスメソッド内で書き換えることはできません。

3. クラスの継承

ES6 以前の継承方式では、主にコンストラクタとプロトタイプチェーンの組み合わせで継承を実装していました。具体的なコードは以下のとおりです。

関数 Rectangle(長さ, 幅) {
            this.length = 長さ
            this.width = 幅
            Rectangle.prototype.getArea = 関数 () {
                this.length * this.width を返す
            }
        }
        関数 Square(長さ) {
            Rectangle.call(this, length, length)
        }
        Square.prototype = Object.create(Rectangle.prototype, {
            コンストラクタ: {
                値: 平方、
                列挙可能: true、
                書き込み可能: true、
                設定可能: true
            }
        })
        var square = 新しい Square(3)
        console.log(square.getArea()); //9
        console.log(square instanceof Square); //true
        console.log(square instanceof Rectangle); //true

上記のコードは、コンストラクターとプロトタイプに静的メソッドを追加して、Rectangle 親クラスを実装します。次に、サブクラス Square は、Rectangle.call(this, length, length) を通じて親クラスのコンストラクターを呼び出します。Object.create は、2 つのプロトタイプ オブジェクトを接続するために内部的に空のオブジェクトを作成し、手動でコンストラクターを自身にポイントします。この継承コードの実装方法は複雑で理解しにくいため、ES6 クラスの作成により継承が簡単になります。extends キーワードを使用して、現在のクラスが継承する必要がある親クラスを指定します。生成されたクラスのプロトタイプは自動的に調整され、super() メソッドを使用して基本クラスのコンストラクターにアクセスすることもできます。具体的なコードは次のとおりです。

クラス Rectangle {
            コンストラクタ(長さ, 幅) {
                this.length = 長さ
                this.width = 幅
            }
            取得エリア() {
                this.length * this.width を返す
            }
        }
        クラスSquareはRectangleを拡張します{
            コンストラクタ(長さ) {
                スーパー(長さ, 長さ)
            }
            取得エリア() {
                this.length + this.length を返す
            }

        }
        var square = 新しい Square(3)
        console.log(square.getArea()); //6
        console.log(square instanceof Square); //true
        console.log(square instanceof Rectangle); //true

上記のコードでは、Square クラスが基本クラスの getArea() メソッドをオーバーライドしています。派生サブクラスの関数名が基本クラスの関数名と同じ場合、派生クラスのメソッドは基本クラスのメソッドをマスクします。同時に、基本クラスのメソッドをサブクラス getArea() { return super.getArea() } で呼び出して展開することもできます。

4. クラスの静的メンバーを継承する

静的メンバー: コンストラクターに直接追加された追加メソッド。たとえば、ES5 でプロトタイプに追加されたメソッドは静的メンバーです。ES6 クラスの導入により、静的メンバーの作成が簡素化されました。メソッド名とアクセサー プロパティ名の前に static キーワードを追加するだけで済みます。たとえば、次のコードは静的メソッドとインスタンス メソッドを区別するために使用されます。

関数 PersonType(名前) {
        this.name = 名前;
    }
    // 静的メソッド PersonType.create = function(name) {
        新しいPersonType(名前)を返します。
    };
    // インスタンスメソッド PersonType.prototype.sayName = function() {
        コンソールにログ出力します。
    }; var person = PersonType.create("ニコラス");

ES6 で静的メンバーを使用するには:

クラス Rectangle {
            コンストラクタ(長さ,幅) {
                this.length = 長さ
                this.width = 幅
            }
            取得エリア() {
                this.length * this.width を返す
            }
            静的作成(長さ、幅) {
                新しい Rectangle(長さ, 幅) を返します
            }
        }
        クラスSquareはRectangleを拡張します{
            コンストラクタ(長さ){
                super(長さ,長さ)
            }
        }
        var square = Square.create(3,4)
        console.log(square.getArea()); //12
        console.log(square instanceof Square); //false
        console.log(square instanceof Rectangle); //true

上記のコードでは、新しい静的メソッド create() が Rectangle クラスに追加されています。このメソッドは継承を通じて Square.create() として存在し、Rectangle.create() と同じように動作します。静的メンバーにはインスタンスを通じてアクセスすることはできないため、アクセスするには常にクラス自体を直接呼び出す必要があることに注意してください。

最後に

以上がこの記事の全内容です。読者の皆様に少しでもお役に立てれば幸いです。よろしければフォローしてください。小白の成長の道では、仕事でよくある問題や技術的なポイントを今後も更新していきます。

以下もご興味があるかもしれません:
  • JavaScript オブジェクト指向クラス継承ケースの説明
  • JSでES6クラスの使い方をすぐにマスター
  • JS タブ プラグインを作成する 2 つの方法 (jQuery とクラス)
  • JSを使用したクラス名の追加と削除の詳細な説明
  • フロントエンドJavaScriptのクラス

<<:  Windows Server win2003、win2008R2、win2012、win2016、win2019 システム バージョン間の違い

>>:  MySQL 8.0.17 をインストールしてリモート アクセスを構成する方法

推薦する

Linux で ARM 開発ボード用のファイルシステムを作成する

1. Busyboxのソースコードをオンラインでダウンロードしてください。コンパイル方法については、...

VUEウォッチリスナーの基本的な使い方の詳しい説明

目次1. 次のコードはwatchの簡単な使用法です2. 即時監視3. ハンドラメソッド4. 深い属性...

MySQL の current_timestamp の落とし穴とその解決策を共有する

目次MySQL の current_timestamp の落とし穴エラーを報告する私の解決策mysq...

MySQL 8.0.13 解凍版のインストールと設定方法のグラフィックチュートリアル

1. インストール1. MySQLをダウンロードするダウンロードアドレス: リンクアドレスブラウザで...

Vue3ルーティングVueRouter4を使用する簡単な例

ルーティングvue-router4 では API の大部分は変更されていないため、変更点のみに焦点を...

CSS3 での 2D および 3D 変換の実装

CSS3 は、要素の 2D 平面変換と視覚的な 3D 空間変換を実装します。2D 変換はより頻繁に使...

MySQL 作成ルーチン権限に関する注意事項

1. ユーザーにルーチン作成権限がある場合は、プロシージャ | 関数を作成できます。 2. ユーザー...

tomcat+nginx を使用してマルチアプリケーション デプロイメントを実装するためのサンプル コード

目次マルチアプリケーションの展開1-Tomcat 構成1.1- プロジェクト構成1.2-サービス構成...

JS 9 Promise 面接の質問

目次1. 複数の .catch 2. 複数の .catch 3. .then と .catch の連...

jsはシンプルな英語-中国語辞書を実装します

この記事では、参考までに、簡単な英中辞典を実装するためのjsの具体的なコードを紹介します。具体的な内...

CSS3 で虫眼鏡効果を模倣するいくつかの方法の原理の分析

記事のタイトルが「模造虫眼鏡」なのはなぜですか?今日お話ししたいのは、一般的に言われているような、マ...

Vue プロジェクト コード分割ソリューション

目次背景目的分割前プロセス設計ディレクトリ構造の設計問題分割後プロセス設計ディレクトリ構造の設計問題...

ボタンをクリックして画像を切り替える JavaScript

この記事の例では、ボタンをクリックすることで画像を切り替えることを実現するJavaScriptの具体...