【ISSUE】JSについて本気出して考えてみた

0

2024年12月23日 22:38

はじめに

こんにちはばーんです
今回はJavaScriptの言語仕様について書いていきます。

JavaScriptの勉強会参加と(https://x-hack.connpass.com/)
その際に勧められた書籍を読んで、自分で得た知識を整理していきます。

なるべく言語仕様書のように堅苦しくなく説明していくよう心掛けますw

今回の対象者

【JavaScriptは殆どオブジェクトである】という言葉の意味が理解できていない方

  • そもそもオブジェクトって何?
  • これってメソッド?プロパティ?
  • console.log("hello world") が "hello world" を表示するまでに何をしているのか?

といったことを解決していきたいと思います。

ゴール

【JavaScriptは殆どオブジェクトである】が理解できる

具体的には下記の内容を理解できればOKだと思っています。

①「そもそもオブジェクトがどういうものか?理解する」

②「JavaScriptがどういうもので構成されているか知る」

③「どういう流れで普段自分たちが②を意識せずに使えているか知る」

第1章: オブジェクト / プロパティ / メソッド って何?

前段の通りJavaScriptは殆どがオブジェクトです。

関数も配列も
※3章で掘り下げます

オブジェクトとは**「名前と値を持つプロパティを格納するコンテナ」**です。
例えば下記のようなオブジェクトがあった場合は、

img

オブジェクト / プロパティ / メソッドを下記のように分類できます。

img

自分自身もオブジェクト、プロパティ、メソッドは混乱していましたが、このように明示できます。

オブジェクトのプロパティへのアクセス方法

どのようにオブジェクトを使用するか?ということです。

オブジェクト名 + ドット + プロパティ名(名前またはキー)でアクセスできます。
ちなみに関数の場合は()をつけることで実行されます。

img

※ドット記法とブラケット記法がありますが、話が逸れるのでブラケット記法については書きません。

Point: console.log()は関数です

※正確には関数ではなくconsoleオブジェクトの中のメソッドの1つですが、伝わりやすくする為上記のような表記としています。

当時JS完全に理解した状態だった自分は、関数と聞くと

img

みたいなモノを想像していました。
しかし、初学者にとっても馴染みの深いconsole.log()が関数だったなんて!と衝撃を覚えました。

Screen Shot 2020-08-04 at 14.29.49.png

このようにchromeのDevtoolにconsole.logを入力すると

ƒ log() { [native code] }

と表記されます。 ƒ はfunctionのことですね^^

第1章まとめ

  • オブジェクトはただの箱
  • 中に0個以上のプロパティを持っている
  • 使う時はオブジェクト名とキーをドットで繋げる
  • 関数を値に入れるとメソッドになる

このことを念頭に読み進めて頂けるとm_ _m

第2章: JSの構成要素を知る

まずここでは、JavaScriptがどのような要素で構成されているか?を見ていきます。

結論から言うとJavaScriptはプリミティブ値とネイティブオブジェクト(コンストラクタ)で構成されています。

プリミティブ

原始的な、基本の みたいな意味ですね。
JavaScriptでは数字、文字列、真偽値などが当てはまります。
(https://developer.mozilla.org/ja/docs/Glossary/Primitive)

ネイティブオブジェクト(コンストラクタ)

はい。こちらがややこしいので詳しく書いていきます。

コンストラクタ(関数)

そもそもコンストラクタ(関数)とは、
new演算子を使って実行されるとオブジェクトを生成する関数です。

ちょっと待って下さい。ブラウザバックしないで欲しい。

img

img

当然といえばそうですが、①はbaanを定義していないので構文エラーが出ます。
②はnew演算子を使って実行しているので空のオブジェクトが生成されています。
これを普段見慣れているような形にすると、

img

この**Object()**の部分がコンストラクタ関数です

ネイティブオブジェクト(コンストラクタ)

そして、原始的に用意されているネイティブオブジェクトは9つです。

Number()

String()
Boolean()
Object()
Array()
Function()
Date()
RegExp()
Error()

これ以外を宣言するとエラーが出ます。

img

ちなみにPersonを使用したい場合は、

img

このようにコンストラクタ関数を宣言すればOKです!
これで想定通りの振る舞いになりました^^

2章まとめ

  • JavaScriptはプリミティブ値とネイティブオブジェクト(コンストラクタ)で構成されている
  • コンストラクタをnewすることでオブジェクトが生成される

第3章: 殆どがオブジェクトである理由を知る

ここではネイティブオブジェクト(コンストラクタ)から、どのようにして普段使っているオブジェクトになっているのかを掘り下げていきます。
その為には1章の冒頭部分を掘り下げていきます。

前段の通りJavaScriptは殆どがオブジェクトです。

関数も配列も

関数オブジェクトについて

関数もオブジェクトです。なので値としてセットできます。
例えば関数の引数であったり、メソッドとして。

img

※メソッドについては1章で触れているので省略します

また、ネイティブオブジェクト(コンストラクタ)についてですが、

img

このようにnewすることで、無名関数を生成しています。
もう少しわかりやすくする為chromeのDevtoolを使います。

Screen Shot 2020-08-04 at 17.09.59.png

無名関数が生成されていますね^^

※ただし、Functionコンストラクタによる関数の生成は推奨されません。これは、JSエンジンによる最適化を妨げたり、他の問題を引き起こしたりする場合があるためです。

配列オブジェクトについて

こちらも関数同様にネイティブオブジェクト(コンストラクタ)をnewしてみます。

img

普段私たちは②を使用していると思います。
が、内部的にはJavaScriptがよしなにやってくれているだけで、配列の生成は①で行われています。

このように普段使用している関数も配列もオブジェクトです。
そして、それらはネイティブオブジェクト(コンストラクタ)より生成されています。

なので**「JavaScriptは殆どオブジェクト」**なのです。

ちょっとまってプリミティブ値は?

2章まとめ

  • JavaScriptはプリミティブ値とネイティブオブジェクト(コンストラクタ)で構成されている

ここで述べているプリミティブ値はどーなんの?
という話ですが、プリミティブ値はオブジェクトでラップされる時があります。
つまり、擬似的にオブジェクトのように振る舞います。

img
本来1(数値)はプリミティブ値なのでtoStringのプロパティを持ちませんが、プリミティブ値のプロパティにアクセスする際に、オブジェクトでラップされるのでこのような表現になります。

3章まとめ

つまり1〜3章をまとめて
**「JavaScriptは殆どオブジェクト」**なのです。

番外編: グローバルオブジェクト / プロトタイプチェーンを知る

自分自身が衝撃を受けた項目があるので、最後に番外編として追記させて頂きます。

グローバルオブジェクト

私たちがconsole.log()を使用する時、consoleオブジェクトについてはそれほど考えないと思います。
ただ、それでもchromeのDevtoolにconsole.logを入力すると使えてしまいます。

それはつまり、JavaScriptがよしなにやってくれてます。
具体的にブラウザは、グローバルオブジェクトとしてwindowオブジェクトを持っています。
※正確にはブラウザを立ち上げたクライアントPCのメモリ上に、グローバルオブジェクトを展開しています

そして、 console はオブジェクトであり、 window のプロパティです。 log はメソッドです。

①まずchromeのDevtoolにwindowを入力します
Screen Shot 2020-08-04 at 19.19.39.png

②windowのプロパティを見てみると大量のプロパティが設定されてあります
Screen Shot 2020-08-04 at 19.21.44.png

③その中にconsoleとlogがありましたね!
Screen Shot 2020-08-04 at 19.22.48.png

img

ちなみにブラウザ上なのでwindow.console.log("hoge") でも動きますが、Node.jsではエラーが出ます(ReferenceError: window is not defined)
**グローバルオブジェクトが違うので。**外面は同じですが内面は違う動きをしています。

プロトタイプチェーン

img

普段私たちは配列を操作する時にこのようにメソッドを使用します(今回は join)。
このような時にmyArrにjoinというプロパティを定義しましたか?

していません。ですが、実際に私たちは明示的にjoinを定義しなくても使えています。
それにはJavaScriptのプロトタイプチェーンが関係しています。

まずプロトタイプチェーンを文面だけで説明すると、

ネイティブオブジェクトコンストラクタ関数(Object, Function, Arrayなど)はオブジェクトを生成する際にprototypeプロパティを継承させます。

待って諦めないで聞いて欲しい。スクロールはもう少し我慢して欲しい。
配列を例に説明していきます。

まず、配列を作る時、普段は

img

と宣言します。
これは、第3章>配列オブジェクトで記載している通り

img

と同意です。つまり、ネイティブオブジェクトコンストラクタ関数である Array()をnewしてインスタンス(この場合myArr)を生成しています。
そして、その際にprototypeというプロパティを継承させています。

prototypeにはjoinというメソッドがあります
Screen Shot 2020-08-04 at 20.16.51.png

なので、私たちは明示しなくともjoinというメソッドが使えるのです。

プロトタイプチェーンは今回の場合であれば、myArrにjoinメソッドがないと判断するとエラーを返すのではなく遡って確認しにいきます。

※最終的にはObject()まで確認しにいきます

自分はプロトタイプチェーンを知ってから格段におまじないみたいなコードが減りました。
何故エラーが出るか?どういう仕組みで?が理解できたので。

簡単に言うとprototypeでリンクしているというイメージでいいかと思います。ブラウザでは__proto__という表記のものもあります。

補足

何点か補足事項があります。

今回書けなかった話

  • thisとは?
  • classとは?
  • インターフェースとは?
  • 予約語とは?

この辺りは次回以降にまとめていこうと思います。

書籍について

開眼!JavaScriptという本です。
とても楽しく読める言語仕様についての本でした^^
ただし、恐らく勉強始めてすぐにこれに出会っていても自分は理解できなかったと思います。

できればJavaScriptで何か動かしてから購入をおすすめします。
(道中呪文みたいな文章結構あるので)

質問 / ツッコミに関して

この記事に関して細部の認識はずれている可能性があります。
技術的なマサカリwは大歓迎ですので、何かあれば遠慮なくコメント頂けると幸いです。

参考サイト

参考にさせていただきましたm_ _m
ありがとうございました^^

https://developer.mozilla.org/ja/docs/Web/JavaScript
https://nodejs.org/api/console.html
https://harakotan.hatenablog.jp/entry/2015/05/17/004707
https://www.tweeeety.blog/entries/2014/02/05

さいごに

今回自分がこの記事を書くきっかけになったのはxhackさんの勉強会がきっかけでした。

参加していなければ理解が浅いまま進んでいたと思います。
この場を借りてお礼申し上げます。ありがとうございましたm_ _m

それではまた^o^/
[cv:issue_marketplace_engineer]

0

診断を受けるとあなたの現在の業務委託単価を算出します。今後副業やフリーランスで単価を交渉する際の参考になります。また次の単価レンジに到達するためのヒントも確認できます。