まず第一に、このコードでは:
MyString.prototype = String.prototype;
MyString.prototype.reverse = function() {
this.split('').reverse().join('');
};
変数MyString.prototype
とString.prototype
は両方とも同じオブジェクトを参照しています!一方に割り当てることは、もう一方に割り当てることです。reverse
メソッドをドロップしたとき、MyString.prototype
それもに書き込んでいましたString.prototype
。だからこれを試してみてください:
MyString.prototype = String.prototype;
MyString.prototype.charAt = function () {alert("Haha");}
var s = new MyString();
s.charAt(4);
"dog".charAt(3);
最後の2行は、プロトタイプが同じオブジェクトであるため、両方とも警告を発します。あなたは本当に拡張しString.prototype
ました。
今あなたのエラーについて。あなたはreverse
自分のMyString
物を呼びました。このメソッドはどこで定義されていますか?プロトタイプでは、これはと同じString.prototype
です。あなたは上書きしreverse
ました。それが最初にすることは何ですか?split
ターゲットオブジェクトを呼び出します。さて、String.prototype.split
動作するためには、を呼び出す必要がありますString.prototype.toString
。例えば:
var s = new MyString();
if (s.split("")) {alert("Hi");}
このコードはエラーを生成します:
TypeError: String.prototype.toString is not generic
これが意味するのはString.prototype.toString
、文字列の内部表現を使用してその処理を実行し(つまり、内部プリミティブ文字列を返す)、文字列プロトタイプを共有する任意のターゲットオブジェクトに適用できないということです。したがって、を呼び出すとsplit
、splitの実装は「ああ、私のターゲットは文字列ではないので、呼び出させてください」と言いましtoString
たが、toString
「私のターゲットは文字列ではなく、ジェネリックではありません」と言ったので、をスローしましたTypeError
。
JavaScriptのジェネリックスについて詳しく知りたい場合は、配列と文字列のジェネリックスに関するこのMDNセクションを参照してください。
これをエラーなしで機能させる方法については、Alxandrの回答を参照してください。
プロトタイプを変更せずに、などの正確な組み込み型を拡張することに関しては、ラッパー、デリゲート、またはサブクラスを作成せずに、実際には拡張しません。しかし、これでは次のような構文は許可されませんString
Date
d1.itervalTo(d2)
ここでd1
、およびは、プロトタイプを拡張しなかっd2
た組み込みクラスのインスタンスです。:-) JavaScriptは、この種のメソッド呼び出し構文にプロトタイプチェーンを使用します。ただそうです。素晴らしい質問ですが...しかし、これはあなたが考えていたものですか?Date