6

JSでメンバー関数を宣言する2つの方法を試しました。

function init() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
}
a = new init();
a.displayName()

function init() {
    var name = "Mozilla";
    displayName = function() {
        alert(name);
    }
}
a = new init();
a.displayName()

displayName()最初の方法はそれを教えてくれましたundefinedFunction私の見方では、名前の付いた型の変数displayNameが作成されているので、機能するはずです。なぜそれが機能しなかったのか説明したい人はいますか?

4

5 に答える 5

13

これがJavaScriptの動作方法であるため、動作しません。コンストラクター関数内で関数を宣言するだけでは、コンストラクター関数によって作成されたオブジェクトに設定されません。オブジェクトと関数の間のリンクを明示的に(オブジェクトに割り当てることによって直接、またはより多くの場合は間接的に)作成する必要があります。プロトタイプ)。

これを行う一般的な方法は、プロトタイプの継承を使用することですが、関数を個々のオブジェクトに直接割り当てることもできます(ただし、「メンバー関数」について説明しました。JavaScriptでそのようなことを行う一般的な方法は、プロトタイプを使用することです)。 。

プロトタイプの継承を設定するには、いくつかの方法があります。従来のブラウザでも幅広いJavaScriptエンジンと互換性のある古典的な方法はprototype、オブジェクトを参照するコンストラクター関数のプロパティを使用することです。そのオブジェクトは、を介して作成されたインスタンスのプロトタイプになりますnew FunctionName。そのオブジェクトにプロパティを追加して、その関数によって作成されたインスタンス間でプロパティを共有します。

したがって、プロトタイプの継承を使用すると、次のようになります。

function Init(name) {
    this.name = name;
}
Init.prototype.displayName = function() {
    alert(this.name);
};

var i = new Init("Mozilla");
i.displayName();

上記に関する注意:

  1. JavaScriptでは、コンストラクター関数は大文字で始まるという圧倒的な慣習があります。だから私はでInitはなくそれを呼んだinit

  2. すべての関数にprototypeは、空白のオブジェクトであるプロパティが自動的にあります。

  3. 関数を参照するというプロパティをそのオブジェクトに追加しますdisplayName

  4. 名前をハードコーディングするのではなくInit、引数として渡します。

  5. 新しく構築されたインスタンスのプロパティに名前を保存していることに注意してください。の呼び出し内でInit、そのインスタンスはとして使用できますthis

  6. 同様に、displayNameはオブジェクトから関数参照を取得する式の一部として呼び出されるため、thisはへの呼び出し内のオブジェクトであり、displayNameそのためthis.nameに名前が付けられます。

  7. 上記のことを簡単にするために、無名関数をに割り当てましたdisplayName。(プロパティには名前がありますが、関数には名前がありません。)実際のコードではそうしない傾向があります。

  8. を介して構築されたすべてのインスタンスは、プロトタイプを介して関数new Initの同じコピーを共有します。displayName

もっと探検する(私のブログで):

JavaScript(および階層)でオブジェクトのクラスを構築することに興味がある場合は、私のLineageツールキットにも興味があるかもしれません。

ES5の時点で、別のオプションがありますObject.create。これにより、コンストラクター関数を使用せずに、オブジェクトを作成してプロトタイプを直接割り当てることができます。ただし、newコンストラクター関数を使用していることを意味するを使用したので、これについては詳しく説明しません。

これで、必要がなければJavaScriptのプロトタイプ機能を使用する必要はありませんたとえば、次のようにすることができます。

function Init(name) {
    var name = name;

    this.displayName = function() {
        alert(name);
    };
}
var i = new Init("Mozilla");
i.displayName();

これはJavaScriptのプロトタイプ機能を使用せず、代わりに、displayName呼び出すたびに新しい関数を作成し、Initそれをオブジェクトに直接割り当てます。(妥当な品質のJavaScriptエンジンは、関数のコードを再利用するのに十分スマートですが、インスタンスごとに異なる関数オブジェクトがあります)。上記では、nameプロパティを完全にプライベートにします。これは、各呼び出しで作成する関数がローカル変数のクロージャーnameであるためです。(詳細:閉鎖は複雑ではありません

于 2012-12-04T10:05:14.240 に答える
6

メンバー関数のようなものを作成するには、コンストラクター関数のプロトタイプに追加する必要があります。

function init() {
    this.name = 'Mozilla';
}
init.prototype.displayName = function() {
    alert(this.name);
}

また、JavaScriptのオブジェクトシステムがどのように機能するかについて何かを読むことを強くお勧めします。MDNにはかなり良い記事があります:https ://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript

于 2012-12-04T10:04:21.127 に答える
3

以下が機能するはずです。

function Init() {
    var name = "Mozilla";
    this.displayName = function() {
        alert(name);
    }
}
a = new Init();
a.displayName()
于 2012-12-04T10:04:14.907 に答える
2

使用できる標準の1つは

var init = (function() {

    var name = "Mozilla"; // Shared by all instances

    function init() {
        this.name = "IE"; // Spesific to the created instance                  
    }    

    init.prototype = {
        displayName: function() {
            alert(name);
            alert(this.name);
        }        
    }

    return init;

})();

var a = new init();
a.displayName();​
于 2012-12-04T10:13:24.550 に答える
0

最初の方法では:

function init(){var name = "Mozilla"; function displayName(){alert(name); }} a = new init(); a.displayName()

function displayName(){}はinit()でのみ呼び出すことができ、プライベート関数に似ているため、object(init())のパブリック関数として使用することはできません。

于 2012-12-04T10:10:41.190 に答える