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

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

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

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

Q&A

4回答

265閲覧

[javascript] isArrayは静的メソッドかどうか

shoshaashin

総合スコア4

JavaScript

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

0グッド

0クリップ

投稿2019/09/04 05:42

編集2019/09/04 07:20

聞きたいこと

javascriptの基本を勉強しているものです。
些細な疑問なのですが、タイトルの通り isArray メソッドは静的メソッドと捉えても良いのでしょうか。
インスタンスから呼び出せない時点でインスタンスメソッドではないということはわかるのですが、
リファレンスを見ても「静的メソッド」という記述がなかったので、ここで質問させていただきました。

自分のイメージとしては、以下のコードのような感じだと思っているのですがどうでしょうか...。

javascript

1function Array(){ 2 //ほにゃらら 3} 4Array.isArray = function(){ 5 //Arrayかどうか判別する処理 6} 7 8Array.isArray(オブジェクト)

回答のほど、よろしくお願いいたします。

追加

tetsunosukeさんが教えてくださった参考ページの例について自分でコードを動かして
確認していたのですが、以下の点が分かりました。
間違っている部分や足りない部分がありましたらご指摘いただけると幸いです。

[分かった点]
・staticメソッド内でのthisはclass自身を指すため、staticメソッドから他のstaticメソッドへは this.staticメソッド で呼び出せる
・クラス内でクラスを明示的に呼び出すことももちろん出来る(例の場合だとStaticMethodClass.staticメソッドのように)
・インスタンスメソッド内のthisはインスタンスを指すため、staticメソッドにアクセスする場合はconstructorプロパティで生成元を辿って参照しなければならない

よろしくお願いいたします。

javascript

1class StaticMethodCall{ 2 3 4 constructor(){ 5 this.className = "StaticMethodCall Class."; 6 7 console.log(StaticMethodCall.staticMethod()); 8 // 'static method has been called' 9 10 console.log(this.constructor.staticMethod()); //インスタンス生成元をconstructorを辿っている 11 // 'static method has been called' 12 } 13 14 static staticMethod(){ 15 return 'static method has been called.'; 16 } 17 18 isThis(){ 19 //staticメソッドでない場合、thisはインスタンスを指す? 20 return ` 21 this: ${this} 22 this === StaticMethodCall: ${this === StaticMethodCall} false 23 this.className = ${this.className} //StaticMethodCall Class. 24 `; 25 } 26 27 static isThis(){ 28 //staticメソッド内でのthisはクラス自体を指す 29 return ` 30 this: ${this} 31 this === StaticMethodCall: ${this === StaticMethodCall} true 32 this.className = ${this.className} //undefined 33 `; 34 } 35} 36 37let sm = new StaticMethodCall(); 38console.log(sm.isThis()); 39console.log(StaticMethodCall.isThis());

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

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

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

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

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

tetsunosuke

2019/09/04 06:05

なるほど。 であれば そのページの左側に、 Array.isArray() ... Array.prototype.push() のようにありますよね。 クラス名.メソッド() のように呼べるのが静的メソッドと言えて、 Array.isArray() は静的メソッドと言えます。 たとえば、 var ar = new Array(); ar.push(1); // ar = [1]; になる。これはインスタンスであるarから呼んでいる Array.isArray(ar); // 結果は true。こちらは静的メソッド。 ar.isArray() と呼び出すことはできません こんな感じで理解できますかね?
shoshaashin

2019/09/04 06:19

prototypeと記述されているか否かで判断すべきだったのですね...。 情報を提供していただき、ありがとうございます。 理解できました!
tetsunosuke

2019/09/04 06:24

ちょっと整理して回答として記載し直しました。
guest

回答4

0

ECMAScript 2019

http://www.ecma-international.org/ecma-262/10.0/
『ECMAScript 2019』には、"instance method" が存在せず、"static method" はあります。
該当部分を読む限りでは、「Array.isArray は static method である」といえそうですが、明確に定義されているわけではないので、曖昧です(次節参照)。

しかしながら、「インスタンスメソッド(instance method) === インスタンスから呼び出せるメソッド」と定義するなら、「Array.isArray は Function の instance method である」ともいえます。

class method

仮に、

  • class method … new 演算子で呼び出し可能なクラスオブジェクトのプロパティにある関数
  • static method … thisキーワードによる処理を行わない関数

と定義した場合、「Array.isArray は "class method" である」が確定しますが、Array.isArray の内部処理を確認するまで、"static method" を明言出来ません(Array.isArray の関数コード内で this を使えば、Array を参照可能です)。
Array.isArray は thisキーワードを使った処理ではないので、「Array.isArray は "static method" である」といえますが、仕様書から処理を追いかけなければ確認不可能な部分です。

※なお、これは私が "class method ", "static method" を仮定義した上での論理ですので、他人に説明する場合は、事前に用語定義を伝えておく必要があります。

Re: shoshaashin さん

投稿2019/09/04 11:29

think49

総合スコア18162

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

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

Lhankor_Mhy

2019/09/04 13:02

> Array.isArray は Function の instance method である 上記について教えていただきたくコメントします。 もちろん定義にもよるのでしょうが、あるクラスの定義にないがそのインスタンスが所持しているメソッドをインスタンスメソッドと呼ぶことに、違和感があります。 私の直観に反して、この使い方は、他言語では一般的なことなのでしょうか? JavaScript はクラスとインスタンスの関係が他言語に比べて緩やかだから、そのような違和感を感じているのかな、とも思うのですが、なんとなくモヤモヤしています。
think49

2019/09/04 22:53

To: Lhankor_Mhy さん ざっくり説明すると、こういうことです。 console.log(Object.getPrototypeOf(Array.isArray) === Function.prototype); // true console.log(Array.isArray instanceof Function); // true 今回の回答は「言葉だけの説明は行き違いが発生するのでコードで説明すべき」の自論に該当しそうなので、親記事に追記しておきますね。
think49

2019/09/04 23:36

個人的には「関数 === 関数呼び出し出来る Object 値([[Call]] を持つObject 型の値)」の認識で「Function のインスタンス」と等価ではないのですが、ECMAScriptで定義されるビルトイン関数は「Function のインスタンス」となるよう実装されている節があります。 理由はおそらく、「そうしなければ、call,apply,bind等のFunction.prototypeに生えているメソッドを容易に使用出来なくなってしまう」でしょう。 (この点は以前、仕様を調べたのですが、記憶が曖昧です。) ES以外の仕様では、この点に触れられていないので、仕様だけを忠実に実装したブラウザ向けにコードを書くと、 const nodeList = document.querySelctorAll('.foo'); Function.prototype.apply.call(nodeList.forEach, [nodeList, element => console.log(element)]); となります。 ただ、Object.prototype.hasOwnProperty() の存在を疑う人はかなりいますが、Function.prototype.apply() の存在を疑う人はあまりいないようです。 JavaScriptコードを書くほとんどの方が、意識はしてないかもしれませんが、「関数 === Functionのインスタンス」の前提でコードを書いているように感じています。
Lhankor_Mhy

2019/09/05 00:26

ありがとうございます。 そこは理解しているつもりなのですが、私の違和感は、以下のようなものです。 たとえば、methodA を定義する clsA と methodB を定義する clsB のミックスインのインスタンス ab は methodB を持つと思います。 実装にもよりますが、Object.getPrototypeOf(ab) === clsA.prototype が真であるとして、「methodB は clsA のインスタンスメソッドである」と言うのに近い違和感があります。 このような言い方は、他言語では通常のことなのかどうか、ということが気になっていることです。 多重継承しかできないJavaScriptでは適切ではない例かもしれませんが、伝わりますでしょうか?
Lhankor_Mhy

2019/09/05 01:32

我ながらめんどくさいことを言ってるなあ、と思いますので、気が向いたときにでも教えていただければ、望外の喜びです。
think49

2019/09/05 04:06

clsA.prototype.methodA = new Function; clsB.prototype.methodB = new Function; Object.getPrototypeOf(ab) === clsA.prototype; // true だとして、 - methodA は clsA のインスタンスメソッドである - methodA は Function のインスタンスである に読めました。 なので、「Array.isArray は Function のインスタンスである」が正でインスタンスメソッドではなかったですね…。 後で修正します。 多重継承に関しては、インスタンスメソッドはあくまで「クラス」に所属するものという認識です。 インスタンス側から見ると、「abはclsAのインスタンスメソッドmethodAを所有している」という感じで、所有関係はあっても所属はクラスにある!1認識ですね。 そのように考えないと、Object.create() で [[Prototype]] を定義したり、prototype系メソッドを余所に移植した時がややこしくなります。
Lhankor_Mhy

2019/09/05 04:34

> 「Array.isArray は Function のインスタンスである」が正 あ、そうか、そうですね。 > そのように考えないと、Object.create() で [[Prototype]] を定義したり、prototype系メソッドを余所に移植した時がややこしくなります たしかに…… 特にミックスインを実装しようと思ったら、やりたくなくてもその手のことをしなきゃいけないですものね。 ありがとうございます。
guest

0

スタティック(静的)メソッドをclassで書くと

javascript

1class User { 2 static staticMethod() { 3 console.log('staticMethod'); 4 } 5} 6 7User.staticMethod(); //'staticMethod'

糖衣構文元のfunctionに戻すと

javascript

1function Userf() {} 2 3Userf.staticMethod = function() { 4 console.log('staticMethod function'); 5}; 6 7Userf.staticMethod(); //'staticMethod function'

インスタンスメソッドはというと

javascript

1class User2 { 2 instanceMethod() { 3 console.log('instanceMethod'); 4 } 5} 6 7var user2 = new User2; 8user2.instanceMethod(); //'instanceMethod'

糖衣構文元のfunctionに戻すと

javascript

1function User2f() {} 2 3User2f.prototype.instanceMethod = function() { 4 console.log('instanceMethod function'); 5}; 6 7var user2f = new User2f; 8user2f.instanceMethod(); //'instanceMethod function'

typeof Arrayがfunctionを返すのでArray.isArrayは静的メソッドです。
Array.isArrayがインスタンスメソッドならtypeof Arrayがobjectを返します。
インスタンスメソッドなら小文字から始まる変数名を付けるのが通例です。

投稿2019/09/04 15:51

querykuma

総合スコア777

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

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

0

リファレンスがどれを見ているかで回答を変えようかと思っていましたが
MDNのものでしたのでこちらを参考回答として記載しておきます。

静的メソッドの呼び出し

こちらでは、

静的メソッドは this キーワードから直接呼び出せません。呼び出すには CLASSNAME.STATIC_METHOD_NAME という風に、クラス名をメソッドの前につけないといけません(クラス外で静的メソッドを呼び出すのと同じやり方です)。

と書いてあるので、

クラス名.メソッド() のように呼べるのが静的メソッドと言えて、Array.isArray() は静的メソッドと言えます。

たとえば、

js

1var ar = new Array(); 2// ar = [1]; になる。これはインスタンスであるarから呼んでいる 3ar.push(1); 4// 結果は true。こちらは静的メソッド。 ar.isArray() と呼び出すことはできません 5Array.isArray(ar); 6// 結果がfalseになる。対象になるものが配列かどうか不明でも使えるのがメリット。 7Array.isArray(1);

こんな感じで理解できますかね?

投稿2019/09/04 06:24

tetsunosuke

総合スコア1292

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

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

shoshaashin

2019/09/04 06:56

載せていただいたものも拝見いたしました。 クラスで実行するものが静的メソッドなのですね。 少しずつですが、リファレンスを読んで学んでいきます。 ありがとうございます。
guest

0

大雑把に言うと「そのとおりです」ということになります。
その意味では、MDNのレファレンスに、cls.method形式で書かれているメソッドは「静的メソッド」と考えてよいです。cls.prototype.method形式で書かれているものは、違います。
ただ、JavaScriptはプロトタイプベースなので、他言語の「静的メソッド」と同一視すると危ういような気がします。

投稿2019/09/04 06:17

Lhankor_Mhy

総合スコア36074

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

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

shoshaashin

2019/09/04 06:26

回答いただき、ありがとうございます。 「cls.method」 こんなヒントもあったのですね ...。気がつきませんでした。 プロトタイプはインスタンス間で共有される暗黙的な参照だと思っているのですが、理解が足りないでしょうか。お答えいただけると嬉しいです。
Lhankor_Mhy

2019/09/04 06:54 編集

概ね合っていると思います。 cls.prototype.method は、 instance = new cls() とした時に、 instance[[prototype]]に、cls.prototypeの参照を持たせます。 そのため、 instance.method とした時に、instance[[prototype]].method を参照し、cls.prototype.method を参照できる、ということです。 ところが、cls.prototype の参照は上書きできるため、cls.prototype と instance[[prototype]] が違うオブジェクトを参照することができます。 このあたりの自由さが結構危ういと思います。
shoshaashin

2019/09/04 07:02

インスタンスはinstance.__proto__(もしくはinstance.constractor.prototype)を辿っているようですね...。 確かにcls.prototypeを{}で空にすると、clsを辿れなくなりました。 頭がこんがらがりそうですが、少しずつ慣れていこうと思います。 詳しく説明していただき、ありがとうございます!
Lhankor_Mhy

2019/09/04 07:07

その instance.constractor も上書きできるんですよね。 なので、 instance.__proto__ と instance.constractor.prototype が違うものになる可能性もある…… 自由すぎますよね。
shoshaashin

2019/09/04 07:24

そうなのですか...!!! 本当に自由ですね。 これ以上立ち入ると頭がパンクするので、一旦止めておきます。。 色々と情報をくださり、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問