[解決済み] JavaScriptで拡張メソッドを書くには?
質問
JSでいくつかの拡張メソッドを記述する必要があります。 私はC#でこれを行う方法だけを知っています。 例です。
public static string SayHi(this Object name)
{
return "Hi " + name + "!";
}
で呼び出されます。
string firstName = "Bob";
string hi = firstName.SayHi();
JavaScriptでこのようなことをするにはどうしたらよいでしょうか?
どのように解決するのですか?
JavaScriptには、C#の拡張メソッドの正確なアナログはありません。JavaScriptとC#は全く異なる言語なのです。
最も近い類似のものは、すべての文字列オブジェクトのプロトタイプオブジェクトを変更することです。
String.prototype
. 一般に、ベストプラクティスは
ではなく
であり、あなたがコントロールしない他のコードと結合されることを意図したライブラリコード内の組み込みオブジェクトのプロトタイプを変更することです。(どのような他のコードがアプリケーションに含まれるかを制御するアプリケーションでそれを行うことは問題ありません。)
もしあなたが
を行う
を変更する場合、そのプロトタイプを
非列挙型
プロパティを
Object.defineProperty
(ES5+、つまり基本的に最新のJavaScript環境、IE8¹以前は不可)を使用します。他の文字列メソッドの列挙可能性、書き込み可能性、および設定可能性に合わせるために、次のようになります。
Object.defineProperty(String.prototype, "SayHi", {
value: function SayHi() {
return "Hi " + this + "!";
},
writable: true,
configurable: true
});
(デフォルトは
enumerable
は
false
.)
古い環境をサポートする必要がある場合は
String.prototype
については、特に、列挙可能なプロパティを作成することで、おそらくうまくいくでしょう。
// Don't do this if you can use `Object.defineProperty`
String.prototype.SayHi = function SayHi() {
return "Hi " + this + "!";
};
それは良くないことですが、逃げられるかもしれません。
決して
でやってください。
Array.prototype
または
Object.prototype
これらのプロパティに列挙可能なプロパティを作成することは、Bad Thing™です。
詳細はこちら。
JavaScriptはプロトタイプの言語です。つまり、すべてのオブジェクトのバックには プロトタイプオブジェクト . JavaScriptでは、そのプロトタイプは4つの方法のうちの1つで代入されます。
-
によって
コンストラクタ関数
をオブジェクトのために使用します (例,
new Foo
でオブジェクトを生成します。Foo.prototype
をプロトタイプとするオブジェクトを生成します)。 -
によって
Object.create
という関数が ES5 (2009)で追加されました。 -
によって
__proto__
アクセッサプロパティ(ES2015+、ウェブブラウザのみ、標準化される前から一部の環境に存在)またはObject.setPrototypeOf
(を使用することができます(ES2015+)。 - プリミティブのメソッドを呼び出すために、JavaScriptエンジンがプリミティブのオブジェクトを作成するとき(これは、"promotion"と呼ばれることもあります。)
つまり、あなたの例では
firstName
は文字列プリミティブなので、これは
String
インスタンスに昇格します。
String
インスタンスのプロトタイプは
String.prototype
. ですから、プロパティを
String.prototype
を参照するプロパティを
SayHi
関数を参照すると、その関数はすべての
String
インスタンスで利用できるようになります (文字列プリミティブは昇格するので、実質的には文字列プリミティブで)。
例を挙げます。
Object.defineProperty(String.prototype, "SayHi", {
value: function SayHi() {
return "Hi " + this + "!";
},
writable: true,
configurable: true
});
console.log("Charlie".SayHi());
C#の拡張メソッドとは、いくつかの重要な違いがあります。
-
(以下 ダグR がコメントで指摘したように) C#の拡張メソッド を呼び出すことができます。
null
リファレンス . もしあなたがstring
という拡張メソッドがあれば、このコード。string s = null; s.YourExtensionMethod();
が動作します(ただし
YourExtensionMethod
を受け取ったときにスローします。
null
をインスタンスパラメータとして受け取ったとき) を投げます。JavaScriptではそうはいきません。
null
はそれ自身の型であり、どのプロパティ参照も
null
のプロパティ参照はエラーを投げます。(そうでなかったとしても、Null 型のために拡張するプロトタイプはありません)。
-
(として
クリス
がコメントで指摘したように)
C#の拡張メソッドはグローバルではありません。拡張メソッドを使用するコードで定義された名前空間が使用されている場合にのみアクセス可能です。(拡張メソッドは静的呼び出しのための構文上の糖分であり、そのため拡張メソッドは
null
.) JavaScriptではそれは当てはまりません。組み込みのプロトタイプを変更すると、その変更は すべて のコードで見られることになります (レルムとは、グローバル環境とそれに関連する固有オブジェクトなどのことです)。ですから、もしあなたがウェブページでこれを行うなら すべて を実行すると、そのページで読み込んだコードが変更されます。これをNode.jsのモジュールでやると。 すべて のコードで読み込まれた場合、そのモジュールと同じ領域で読み込まれたコードは変更を見ます。どちらの場合も、これがライブラリコードでこれを行わない理由です。(ウェブワーカーと Node.js ワーカスレッドは独自のレルムにロードされるので、メインスレッドとは異なるグローバル環境と異なるイントリンジックスを持っています。しかし、そのレルムはまだすべてのモジュールと共有されています それらは をロードします)。
¹ IE8 には
Object.defineProperty
がありますが、これは DOM オブジェクトにのみ作用し、JavaScript オブジェクトには作用しません。
String.prototype
はJavaScriptオブジェクトです。
関連
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] JavaScriptでメールアドレスを検証するのに最適な方法は何ですか?
-
[解決済み] JavaScriptでタイムスタンプを取得する方法は?
-
[解決済み] 2つのJavaScriptオブジェクトのプロパティを動的にマージするにはどうすればよいですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C#で、Nullオブジェクトに対して拡張メソッドを呼び出すとどうなるか?
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
-
[解決済み] Node.jsでbase64エンコードされた画像をAmazon S3へアップロードする
-
[解決済み] Google maps API V3 - 同一地点に複数のマーカーを設置する。
-
[解決済み] 文字列がすべて同じ部分文字列で構成されているかどうかを調べるにはどうすればよいですか?
-
[解決済み] node.jsで文字列のsha1ハッシュを取得するにはどうすればよいですか?
-
[解決済み] 兄弟ノードを選択する方法はありますか?
-
[解決済み] Chromeの拡張機能開発にWebStormを使用するにはどうすればよいですか?
-
[解決済み] JavaScriptとLuaの微妙な違い [終了しました]
-
[解決済み] JavaScriptでDIVを表示・非表示にするには?