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

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

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

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

Q&A

解決済

3回答

2210閲覧

javascriptのプロトタイプチェーンについて

yusukexyusuke

総合スコア52

JavaScript

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

0グッド

3クリップ

投稿2016/01/03 06:10

よろしくお願いします。

只今、
http://www.amazon.co.jp/gp/product/4873116813/ref=od_aui_detailpages00?ie=UTF8&psc=1
を読みながらjavascriptを勉強しております。

プロトタイプチェーンについて学んでるのですが、
自分の認識が正しいのか自信がありません。
以下の認識であってますでしょうか。
もし間違っていたらご指摘いただけると嬉しいですm(__)m

/********** ここから **********/
javascriptには標準でビルトインされている
Function,Object,Date...
などのビルトインオブジェクトがあります。

これらはコンストラクタであります。
コンストラクタは関数であり、
関数はオブジェクトであります。

function Function()
function Object()
function Array()
と同意義だと思います。
(実際にchromeのコンソールで試した所、
Function => function Function()
となりました。)

これらのビルトインオブジェクトのconstructorを調べると、
以下のようになっておりました。

Object.constructor => function Function() Date.constructor => function Function() Function.constructor => function Function() Function.constructor.constructor => function Function()

つまり、
Function,Object,Date...のビルトインオブジェクトはFunctionにより生成されていて、
FunctionもFunction自身から生成されています。

図にまとめました。
イメージ説明
/********** ここまで **********/

ここで疑問があります。

Function.constructor.constructor.constructor.constructor => function Function()

となりますし、
FucntionはFunctionから作られているので、
ここは無限ループのような感じになるのでしょうか。

ここについて書かれている記事が見つからず、
気になって仕方がありません。

このような認識であっているのか、
教えて頂けませんでしょうか。

どうぞ宜しくお願い致します。

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

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

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

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

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

guest

回答3

0

ベストアンサー

コンストラクタは関数だと思っていてもいいですが、
厳密にはコンストラクタと関数は別の独立した存在と考えることが出来ます。
大雑把にコンストラクタとは「new X」と呼べるX、関数は「X()」と呼べるXと定義すると、
もし「new X」と呼べるが「X()」と呼べないものが存在すれば、それは関数ではないコンストラクタとなります。

例えばclass構文で作ったクラスコンストラクタはその様な挙動をします。
超厳密に言うと「()で呼ぶための設計が用意されていない」というものではなく、
「()で呼ばせない設計が用意されている」ということなので少しニュアンスは異なりますが、
大雑把に言えば一般関数のように呼んだりできません。

また、一般関数のように呼んだりできないという点で言うと、()で呼ぶと例外を投げるコンストラクタ関数は多くあります。
「()で呼ばせない設計が用意されている」というものではなく、
「()で呼ばれた後の処理で例外を投げる」というものです。
これは呼ぶステップまでは確実に到達しているので、関数と認めたほうが良いと思いますが、
使う上では「()定義なし」「()定義で拒否」「()処理で拒否」は全て同じですし難しいですね。

投稿2016/01/04 11:39

編集2016/01/04 11:56
jser

総合スコア100

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

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

think49

2016/01/04 15:41

個人的には「コンストラクタ呼び出し可能な関数」「関数呼び出し(function call)可能な関数」で表現していますね。 ES6 的に表現するならば [[Construct]], [[Call]] の有無で区別できます。 - コンストラクタ … [[Construct]] を持つオブジェクト(IsConstructor) - 関数 … [[Call]] を持つオブジェクト(IsCallable, typeof operator) GC47 では下記コードでそれぞれ TypeError になりますが、ES6 仕様のどこをみても TypeError になる記述がないのでもやもやします。 new parseFloat; // TypeError: function parseFloat() { [native code] } is not a constructor Map(); // TypeError: Constructor Map requires 'new' typeof Map === 'function' なので [[Call]] を持っていないわけではないと思いますが…。
yusukexyusuke

2016/01/26 06:47

jserさん 超厳密なご説明ありがとうございます! 細かい部分の理解も深めたいとおもっておりますので、 とても参考になりました! ありがとうございます・
guest

0

ES6 で FunctionFunction をプロトタイプに持ち、Function.prototype.constructor === Function と規定されていますので、循環参照の認識で合っています。

開発者ツールの console でも簡単に確認できるのでお使いのブラウザで検証してみると良いと思います。

JavaScript

1console.log(Function.constructor === Function); // true 2console.log(Function.hasOwnProperty('constructor')); // false 3console.log(Function.prototype.constructor === Function); // true 4console.log(Function instanceof Function); // true

Re: yusukexyusuke さん

投稿2016/01/03 15:15

think49

総合スコア18162

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

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

yusukexyusuke

2016/01/03 17:40

think49様 ご回答ありがとうございます! >循環参照の認識で合っています。 この認識で問題ないのですね! リンクもありがとうございます。 consoleで検証しながら添付の画像を作成したのですが、 1人でやっていると自信が持てずで質問させていただきましたm(__)m
guest

0

Function の constructor が Function であるという意味では無限ループであっています。
どこまでドットで繋げようと永遠に同じものが返されるでしょう。

これらのビルトインオブジェクトのconstructorを調べると、

以下のようになっておりました。

ちょっと注意していただきたいのが、質問者さんが調べているのはビルトインオブジェクトのconstructorではなく、ビルトインオブジェクトのコンストラクターのコンストラクターです。

たとえば[](空配列のリテラルです)はビルトインオブジェクトである配列型のオブジェクトです。
これに対して、ビルトインオブジェクト[]のコンストラクターがArrayです。
→ 実際、[].constructorArrayが返されます。
ということは、Array.constructorは、[].constructor.constructorと等価で、ビルトインオブジェクト[]のコンストラクターのコンストラクターということになります。

ビルトインオブジェクト自体([]など)は関数オブジェクトではありません。
(ただし関数もビルトインオブジェクトなので、厳密には「とは限りません」と言った方が良いでしょうか)

ただし、ビルトインオブジェクトとは関係なく、何らかのオブジェクトの「コンストラクター」と言った時点で、それは間違いなく関数オブジェクトです。
関数オブジェクトであるということは、そのコンストラクターはFunctionになります。

XXXのコンストラクターと言えば、XXXを初期化する役割を果たした関数のことです。
では、すべての関数オブジェクトはFunctionを通じて初期化されたのか、というとそうではありません。
ビルトインオブジェクトはあくまでビルトインされているので、最初から初期化された状態です。
ただ便宜上、Functionで初期化されたことになっています。ユーザー定義の関数とビルトインの関数の振る舞いに整合性があったほうがいいからでしょう。

ちなみに、実際にはJavaScriptの実装系の初期化と同時に初期化されているというイメージでしょう。
そこまで行くと僕も詳しくないのですが、たとえばChromeのV8 JS エンジンなら、C++でできています。
V8においては、Function() { [native code] }というのはC++のことです。

投稿2016/01/03 13:37

tozjp

総合スコア790

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

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

yusukexyusuke

2016/01/03 17:37 編集

tozjp様 ご回答ありがとうございます! まだ納得できない部分があります。。。 もしよろしければお付き合い頂けると幸いです。 >ちょっと注意していただきたいのが、質問者さんが調べているのはビルトインオブジェクトのconstructorではなく、 ビルトインオブジェクトのコンストラクターのコンストラクターです たとえば[](空配列のリテラルです)はビルトインオブジェクトである配列型のオブジェクトです。 『空配列のリテラル』という表現がわからないのですが、 `var hoge = new Array(1,2,3)` という書き方ではなく `[1,2,3]`のように記述することを配列リテラルと呼ぶのではないでしょうか。 []自体がビルトインオブジェクトにあたるのでしょうか。 ビルトインオブジェクトは、 `Date`,`Function`,`Arraya`,`Object` などの関数オブジェクト(コンストラクタ)がそれに当たるというの認識なのですが、 違いますでしょうか。 リテラルとしては `""(文字列リテラル)`、` {}(オブジェクトリテラル)`、`[](配列リテラル)` 等があると思います。 リテラルとはプログラム中においてnew演算子を使わないでオブジェクトを生成する記法という認識です。 >これに対して、ビルトインオブジェクト[]のコンストラクターがArrayです。 → 実際、[].constructorでArrayが返されます。 ということは、Array.constructorは、[].constructor.constructorと等価で、ビルトインオブジェクト[]のコンストラクターのコンストラクターということになります。 ここでいう[]は空の配列型のオブジェクトですよね。 なので[].construcorがArrayを返すのは納得ですm(__)m >ビルトインオブジェクト自体([]など)は関数オブジェクトではありません。 (ただし関数もビルトインオブジェクトなので、厳密には「とは限りません」と言った方が良いでしょうか) 『[]など』と書かれておりますが、 他には何があるか教えて頂けませんでしょうか。 どうぞ宜しくお願い致します。
think49

2016/01/04 03:06 編集

To: tozjp さん > ということは、Array.constructorは、[].constructor.constructorと等価で、ビルトインオブジェクト[]のコンストラクターのコンストラクターということになります。 ES6 仕様としてもGCの挙動を見ても Array.constructor === Array.prototype.constructor だと思うのですが、私の認識違いでしょうか。 http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.constructor console.log(Array.hasOwnProperty('constructor')); // false console.log(Array.prototype.constructor === Array); // true To: yusukexyusuke さん > `""(文字列リテラル)`、` {}(オブジェクトリテラル)`、`[](配列リテラル)` ES6 ではObject初期化子(Object Initializer)、Array初期化子(Array Initializer)と呼びますね。 オブジェクト関連はリテラル(定数)ではないので区別されています。 http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer http://www.ecma-international.org/ecma-262/6.0/#sec-array-initializer
tozjp

2016/01/04 15:35 編集

yusukexyusukeさん > ビルトインオブジェクトは、 > `Date`,`Function`,`Arraya`,`Object` > などの関数オブジェクト(コンストラクタ)がそれに当たるというの認識なのですが、 > 違いますでしょうか。 すみません、僕が思い違いをしていました。そのとおりですね。 中盤部分の思い違いに基づいた回答はばっさりと無視してください。 > リテラルとはプログラム中においてnew演算子を使わないでオブジェクトを生成する記法という認識です。 これについてはそうとも限りません。 (think49さんのコメントにある件もありつつ) 1とか"あ"とかプリミティブな値を記述する場合もリテラルです。 プログラムに値を認識させる手段として、値を得るための何らかの処理を行う場合と、値を直接ソースコードに記述する場合がありますが、後者を一般的にリテラルと呼んでいます。 リテラル自体はプログラム全般の用語で、言葉の意味は言語によって変わったりはしないのですが、何をリテラルとし何を処理とするかが言語仕様とか文脈に依存してるという感じです。 think49さん > ES6 仕様としてもGCの挙動を見ても Array.constructor === Array.prototype.constructor だと思うのですが、私の認識違いでしょうか。 Array.constructor === Array.prototype.constructor は false ですよね。 しかも僕も思い違いがありカオスなことになっているのでどのあたりに認識違いを感じられたのかよく分かりませんが、僕が思い違いであった時点で既に解決する内容だったでしょうか。
think49

2016/01/05 06:50

To: tozjp さん 失礼しました。Function.prototype.constructor === Function だった事実から私もいろいろと認識違いをしていたようです。 Array.hasOwnProperty('constructor'); // false Object.getPrototypeOf(Array) === Function.prototype; // true Array.constructor === Function.prototype.constructor; // true Array.prototype.constructor === Array; // true ですね
yusukexyusuke

2016/01/26 06:45

tozjpさん think49さん お付き合いいただきありがとうございます!!! 理解が深まりました! またお願いします!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問