とある書籍を読んでいて、javascriptで、文字列を逆転する際に以下のような関数を作成する記述がありました。
js初心者のため、どういった意味なのか分かりかねてます。
ぜひ理解するのにご協力ください。
###前提・実現したいこと
String.prototype.reverse = function (){
}
という記載の意味
###発生している問題
String.prototype.reverse = function ()の記載の意味
(理解度としては「無名関数?? なぜ」みたいなレベルです)
###ソースコード
String.prototype.reverse = function (){ return this.split("").reverse().join(""); }
こちらの後で
x.toString().reverse() ....
###その他
ぜひ参考ページがありましたら勉強のためお教えいただけると嬉しいです。お手数ですがよろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
この問題を解くには new String()
と「プロトタイプチェーン」を理解する必要があります。
'hoge' と new String('hoge')
'hoge'
と new String('hoge')
は厳密には異なりますが、数多くの部分で似た性質を持ちます。
平易な説明にする為に詳細を省略しますが、文字列は new String()
と**ほぼ等価*です。
プロトタイプチェーン
JavaScript ではプロパティ参照時にプロトタイプチェーンの原理によってプロパティを検索します。
プロトタイプチェーンについては詳細な記事がいくつもありますので参照して下さい。
- 継承とプロトタイプチェーン - JavaScript | MDN
- プロトタイプチェーンについて
- や...やっと理解できた!JavaScriptのプロトタイプチェーン - maeharin log
- 九章第三回 継承 — JavaScript初級者から中級者になろう — uhyohyo.net
文字列は new String
とほぼ等価ですので、'hoge'
は String.prototype
上のプロパティを使用できます。
var str = new String('Hello, World!'); str.slice(7); // "World!" (String のインスタンスなので String.prototype.slice を使用できる) String.prototype.slice === str.slice; // true var str = 'Hello, World!'; str.slice(7); // "World!" (new String と「ほぼ等価」なので String.prototype.slice を使用できる) String.prototype.slice === str.slice; // true
投稿2015/11/02 15:51
総合スコア18156
0
JavaScriptについて二つのことを理解しておく必要があります。
- prototypeを変えれば_proto_※1も変わる。
- 関数もオブジェクトにすぎない。
※1 _proto_の"_"の部分ですが実際は半角"_"が2個です。teratail上では__斜体__のマークアップとして解釈されるため、それを回避するのに全角の"_"を使っています。以下、同様です。
1. prototypeを変えれば_proto_も変わる。
JavaScriptのprototypeチェーンの仕組みは理解しているでしょうか?ここら辺は情報が多いので検索して、一番理解しやすいのを探すといいかと思います。どこがいいかは私もわかりません。
とりあえず、簡単な解説です。全てのオブジェクトは_proto_
というプロパティを持ちます(実装によっては無い場合もありますが、ここでは一般的な実装で話をします)。ある文字列(String)オブジェクトであるs
について考えます。s.reverse
はどうなるかと言いますと、まず、s
にreverse
というプロパティがないかを確認します。ただの文字列ですので、reverse
はありません。そこで次はs._proto_
にreverse
というプロパティがないかを確認します。s
はStringのオブジェクトなので、このs._proto_
がString.prototype
と同じ物になっています。どうしてそうなのかというとJavaScriptではそういう仕組みになっているとしか言い様がありません。もし、s._proto_
、つまりString.prototype
にもreverse
というプロパティがなかったら、次はs._proto_._proto_
(これはString.prototype._proto_
と同じです)を見に来ます。ずっと見つからない場合は、最終的にObject.prototype
まで辿り着きますが、Object.prototype._proto_
はnull
なので、そこで検索がとまり、エラーになります。この仕組みをprototypeチェーンと呼びます。
話を戻しましょう。String.prototype
にreverse
が無いかを確認するということでした。そこでString.prototype.reverse = function(){略};
と書いたところが意味を持つのです。つまりこれはString.prototype
にreverse
というプロパティをfunction(){略}
に代入する(設定する)という意味です。つまり、事前に書いてあれば、String.prototype
にreverse
があると言うことになるので、その実体であるfunction(){略}
を受け取ります。s.reverse
はfunction(){略}
であることがわかりました。なのでs.reverse()
はfunction(){略}()
となるというわけです。
おっと、ここで注意事項があります。this
の束縛です。function(){略}()
と書きましたが、正しくはfunction(){略}.call(s)
と書いたような動作になります。つまり、function(){略}
内においてthis
がs
になり(束縛され)ます。上のコードの例で言うと、this.split("").reverse().join("")
の部分がs.split("").reverse().join("")
になるという意味です。
2. 関数もオブジェクトにすぎない。
JavaScriptでは関数もただのオブジェクトです。よくある関数定義は下記のように書くかと思います(この書き方を関数宣言といいます)。
JavaScript
1function f() { 2 console.log("teratail"); 3} 4f(); // コンソールに teratail と出力
ですが、実はこれは、
JavaScript
1var f; 2f = function() { 3 console.log("teratail"); 4}; 5f(); // コンソールに teratail と出力
とほぼ同じ※2です(こちらの書き方を関数式と言います)。実際に、どちらで書いても問題ありません。
※2 厳密には動作が少し異なります。前者はファイル読込時にf
が定義されます(巻き上げという)が、後者は実際の行が評価されるまでf
が定義されません。また、前者では関数に名前(name
プロパティで参照可能)がついていますが、後者にはついていません。しかし、ただの関数として扱う場合はどちらを使っても問題ありません。
つまり、JavaScriptというのは関数も一つのオブジェクトにすぎず、function f() {略}
のような関数宣言は変数に名前付き関数を代入しているのと同じなのです。逆に言うとf = function() {略};
のような変数に関数を代入する関数式の書き方は関数宣言の別の書き方と言ってもいいのです。
では戻ってString.prototype.reverse = function(){略};
を考えます。これはString.prototype.reverse
という関数を定義している関数式です。先ほどみた関数式の例では普通の変数への代入でしたが、別になんらかのオブジェクトのプロパティへの代入でも問題ないのです。なぜなら、JavaScriptは全ての関数をただのオブジェクトとして扱っているので、変数やプロパティに数字を入れるのと同じように扱えるからです。そして、呼び出す時はf()
と書けるのと同じようにString.prototype.reverse()
※3ともかけますし、call
やapply
も使えるということです。
※3 この場合は、this
はString.prototype
に束縛されるので、上のコード例のような実装では意味がありませんが…。
投稿2015/11/02 11:40
総合スコア21733
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。