質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

2回答

5307閲覧

「String.prototype」の意味

kimura511

総合スコア10

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2015/11/02 09:25

とある書籍を読んでいて、javascriptで、文字列を逆転する際に以下のような関数を作成する記述がありました。
js初心者のため、どういった意味なのか分かりかねてます。
ぜひ理解するのにご協力ください。

###前提・実現したいこと
String.prototype.reverse = function (){
}
という記載の意味

###発生している問題
String.prototype.reverse = function ()の記載の意味
(理解度としては「無名関数?? なぜ」みたいなレベルです)

###ソースコード

String.prototype.reverse = function (){ return this.split("").reverse().join(""); }

こちらの後で

x.toString().reverse() ....

###その他
ぜひ参考ページがありましたら勉強のためお教えいただけると嬉しいです。お手数ですがよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

この問題を解くには new String() と「プロトタイプチェーン」を理解する必要があります。

'hoge' と new String('hoge')

'hoge'new String('hoge') は厳密には異なりますが、数多くの部分で似た性質を持ちます。
平易な説明にする為に詳細を省略しますが、文字列は new String() と**ほぼ等価*です。

プロトタイプチェーン

JavaScript ではプロパティ参照時にプロトタイプチェーンの原理によってプロパティを検索します。
プロトタイプチェーンについては詳細な記事がいくつもありますので参照して下さい。

文字列は 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

think49

総合スコア18156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

JavaScriptについて二つのことを理解しておく必要があります。

  1. prototypeを変えれば_proto_※1も変わる。
  2. 関数もオブジェクトにすぎない。

※1 _proto_の"_"の部分ですが実際は半角"_"が2個です。teratail上では__斜体__のマークアップとして解釈されるため、それを回避するのに全角の"_"を使っています。以下、同様です。

1. prototypeを変えれば_proto_も変わる。

JavaScriptのprototypeチェーンの仕組みは理解しているでしょうか?ここら辺は情報が多いので検索して、一番理解しやすいのを探すといいかと思います。どこがいいかは私もわかりません。

とりあえず、簡単な解説です。全てのオブジェクトは_proto_というプロパティを持ちます(実装によっては無い場合もありますが、ここでは一般的な実装で話をします)。ある文字列(String)オブジェクトであるsについて考えます。s.reverseはどうなるかと言いますと、まず、sreverseというプロパティがないかを確認します。ただの文字列ですので、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.prototypereverseが無いかを確認するということでした。そこでString.prototype.reverse = function(){略};と書いたところが意味を持つのです。つまりこれはString.prototypereverseというプロパティをfunction(){略}に代入する(設定する)という意味です。つまり、事前に書いてあれば、String.prototypereverseがあると言うことになるので、その実体であるfunction(){略}を受け取ります。s.reversefunction(){略}であることがわかりました。なのでs.reverse()function(){略}()となるというわけです。

おっと、ここで注意事項があります。thisの束縛です。function(){略}()と書きましたが、正しくはfunction(){略}.call(s)と書いたような動作になります。つまり、function(){略}内においてthissになり(束縛され)ます。上のコードの例で言うと、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ともかけますし、callapplyも使えるということです。

※3 この場合は、thisString.prototypeに束縛されるので、上のコード例のような実装では意味がありませんが…。

投稿2015/11/02 11:40

raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問