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

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

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

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

Q&A

3回答

915閲覧

Dateクラスのconstructorに処理を追加することは可能なのか?

domidomi

総合スコア34

JavaScript

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

0グッド

3クリップ

投稿2019/06/18 09:51

編集2019/06/19 13:39

##※注意
通常組み込みオブジェクトの内容を変更することは推奨されておりません。
学習用途以外では行わないようにしてくださいませ。

##本文

Dateクラスについてchromeのコンソールを用いていろいろいじってみています。
その中でふとDateクラスのconstructorに処理を追加してみようとしました。
しかし思ったような挙動になりませんでした。

javascript

1Date.prototype.constructor(); 2// Tue Jun 18 2019 18:27:27 GMT+0900 (日本標準時) 3 4var itti = Date.prototype.constructor 5var aaa = function(...args){ 6 itti(...args) 7 console.log('abesi'); 8} 9Date.prototype.constructor = aaa; 10 11itti(); 12// Tue Jun 18 2019 18:27:43 GMT+0900 (日本標準時) 13aaa(); 14// abesi 15Date.prototype.constructor(); 16// abesi

以下のような出力を期待していたつもりです。(現実は上)

javascript

1Date.prototype.constructor() 2// Tue Jun 18 2019 18:27:43 GMT+0900 (日本標準時) 3// abesi

関数の値渡しミスなどが理由ならエラーが出るかとも思ったのですがエラーも出ずこの状態になったことで更によく解らなくなってしまいました・・・
お時間ありましたらご教示いただけると幸いです。
##補足

javascript

1class Aa { 2 constructor(){ 3 console.log("hidebu"); 4 } 5} 6Aa.prototype.constructor(); 7//Uncaught TypeError: Class constructor Aa cannot be invoked without 'new'

適当なクラスを作ってコンストラクター関数だけ使用しようとしてみるとエラーとなります。
ビルトインオブジェクト故にできない事なのかも?わからないですが・・・

##追記1
いろいろお答えいただき本当にありがとうございます。
当初私が作ってみたいと思った状況は

javascript

1class Aa extends Date{ 2 constructor(...arg){ 3 super(...arg); 4 console.log("アベシ"); 5 } 6}; 7Date = Aa; 8new Date() 9// アベシ 10// 22:27:02.908 Wed Jun 19 2019 22:27:02 GMT+0900 (日本標準時)

で作ることが出来ました。
しかし未だ

javascript

1var itti = Date.prototype.constructor 2var aaa = function(...args){ 3 itti(...args); 4 console.log('abesi'); 5} 6Date.prototype.constructor = aaa;

を行ってから

javascript

1new Date()

を行うとabesiと出てこない事の理由がわかりません。

また、私はプログラムについて何か仕事をしているわけでもなんでもなく、
ただの好奇心からの質問です。混乱させてしまいすみません。

仕事で行う人がいたらかなり危険だとも思いますので、
もしこの質問の最上に注意を書かせていただきました。

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

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

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

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

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

Lhankor_Mhy

2019/06/18 10:01

「出力」とは具体的にはなんでしょうか? 「出力」がconsole.logなら、 var aaa = function(...args){ itti(...args) ↓ var aaa = function(...args){ console.log(itti(...args)); という話ではなく?
domidomi

2019/06/18 10:16

みていただきありがとうございます。 すみません出力という表現は適していなかったです。 なってほしい状況はnew Dateした際に、自作の処理が走りDateインスタンスも生成されていてほしかったという意味です。 あくまでDateという元の関数の言葉を変えずにコンストラクターに追加変更を加えることはできないかなー?と思った次第です。
Lhankor_Mhy

2019/06/18 10:25 編集

> 自作の処理が走りDateインスタンスも生成されていてほしかった 生成されていると思うのですが…… ただ、どこからも参照していないだけで。
guest

回答3

0

その中でふとDateクラスのconstructorに処理を追加してみようとしました。

やるべきではありません

Webページ1ページに収まる程度のJavaScriptで試験的にやるのなら話は別ですが、他人の作ったライブラリも組み込んで開発するようなプロジェクトで、組み込みのDateの挙動を変えてしまうと、どこにどんな影響が出るか、予想もできません。よほどの覚悟を持ってやるのでない限り、禁じ手です。

投稿2019/06/18 12:16

maisumakun

総合スコア145184

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

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

0

追記に関して、回答を追記させていただきます。

代入をDate自体に行い、
aaa関数で、ittiをreturnさせる必要があるようです。

javascript

1var itti = Date.prototype.constructor; 2 3var aaa = function(...args){ 4 console.log('abesi'); 5 // ittiをnewで返す 6 return new itti(...args); 7}; 8// prototype.constructorではなく、Date自体に代入してしまう。 9Date = aaa; 10 11const test = new Date();// abeshi

Lhankor_Mhyさんのおっしゃる通り、
元質問コードだと、別物になってしまうのでしょう。
それは、constructorの仕様かと思います。
setterやgetterが関係あるかと思います。
具体的なソースは、調べきれていません。
申し訳ございません。

これは、本当にお遊びでしかやれませんね。

-------- 下記元回答 --------

maisumakunさんのおっしゃる通り、よほど何か理由がない限り、やるべきではありません。
prototypeという、JavaScriptのprototypeから、元の関数などを拡張するライブラリがありますが、
あれも、相当検証が重ねられ、慎重に慎重に作成されているライブラリなはずです。

なので、視点を変え、
クラス構文で、Dateクラスを継承する、というのはいかがでしょうか。

javascript

1class DateExtend extends Date { 2 constructor(...args){ 3 super(...args); 4 console.log('abesi'); 5 } 6} 7 8console.log(new DateExtend());

これであれば、constructor実行時に、
別の処理も行えますし、
元のDateを侵すこともありません。

投稿2019/06/18 14:27

編集2019/06/20 03:29
miyabi_takatsuk

総合スコア9528

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

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

0

以下のような出力を期待していたつもりです。

出力されています。

js

1Date.prototype.constructor(); 2// Tue Jun 18 2019 18:27:27 GMT+0900 (日本標準時) 3 4var itti = Date.prototype.constructor 5var aaa = function(...args){ 6 console.log(itti(...args)); 7 console.log('abesi'); 8} 9Date.prototype.constructor = aaa; 10 11Date.prototype.constructor(); 12//Tue Jun 18 2019 19:52:00 GMT+0900 (日本標準時) 13//abesi

適当なクラスを作ってコンストラクター関数だけ使用しようとしてみるとエラーとなります

new演算子をつけずに呼び出したのがエラーの原因ではないでしょうか。

js

1class Aa { 2 constructor(){ 3 console.log("hidebu"); 4 } 5} 6Aa(); 7//Uncaught TypeError: Class constructor Aa cannot be invoked without 'new'
コメントを受けて追記

new Dateを行った際にabesiと表示されないのはなぜでしょうか?

違うものだからだと思います。

js

1console.log( Date === Date.prototype.constructor ); 2//true 3 4var itti = Date.prototype.constructor 5var aaa = function(...args){ 6 console.log(itti(...args)); 7 console.log('abesi'); 8} 9Date.prototype.constructor = aaa; 10 11console.log( Date === Date.prototype.constructor ); 12//false

記述の処理を走らせてからDate.prototype.constructor("2003")と引数を入れても現在時刻が帰ってくるのはなぜでしょうか?

確認してみましたが、記述の処理を走らせる前からそうでした。
きちんとECMAScriptの仕様を調べていませんが、Chrome、Firefox、IE11で同じ動作でした。おそらく仕様ではないかと。

js

1console.log( Date.prototype.constructor("2003"), Date("2003") ); 2//Tue Jun 18 2019 21:08:31 GMT+0900 (日本標準時) Tue Jun 18 2019 21:08:31 GMT+0900 (日本標準時) 3 4var itti = Date.prototype.constructor 5var aaa = function(...args){ 6 console.log(itti(...args)); 7 console.log('abesi'); 8} 9Date.prototype.constructor = aaa; 10 11console.log( Date.prototype.constructor("2003"), Date("2003") ); 12//Tue Jun 18 2019 21:08:31 GMT+0900 (日本標準時) 13//abesi 14//undefined Tue Jun 18 2019 21:08:31 GMT+0900 (日本標準時)
質問の追記にあわせて追記

abesiと出てこない事の理由がわかりません

なるほど……
質問等を拝見して、domidomiさんは「new Date()としたときにDate.prototype.constructorが呼び出される」と勘違いされているのではないかな、と感じました。(違ったらすみません)

new Date()とした時に呼び出されるのは、普通にDateです。他の何者でもありません
たしかに、Date === Date.prototype.constructorである時は、Date.prototype.constructorが呼び出されると考えても間違いではありませんが、それはたまたまDate === Date.prototype.constructorであった、つまりDate.prototype.constructorDateを参照していたから結果的には間違いではなかった、というだけのことです。

コメントを受けて追記

new Date()した際にインスタンスを生成する際最初に必ず走る処理を定義するconstructorが走ると思っています

それは違います。

js

1var f = function(){ 2 alert('私はfです') 3} 4 5f.prototype.constructor = function(){ 6 alert('私はf.prototype.constructorです') 7} 8 9f(); 10//私はfです 11 12new f(); 13//私はfです

投稿2019/06/18 11:02

編集2019/06/20 06:15
Lhankor_Mhy

総合スコア36115

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

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

domidomi

2019/06/18 11:29

回答ありがとうございます。 ・new Dateを行った際にabesiと表示されないのはなぜでしょうか? ・記述の処理を走らせてからDate.prototype.constructor("2003")と引数を入れても現在時刻が帰ってくるのはなぜでしょうか?
Lhankor_Mhy

2019/06/20 05:59

「たまたま」は言い過ぎましたね。 関数は、誰かが手を加えない限り、 func === func.prototype.constructor となるので、「誰も Date.prototype.constructor にいたずらをしていなかったので結果的には間違いではなかった」という言い方が正しいでしょうか。
domidomi

2019/06/20 06:06

・new Date()した際にインスタンスを生成する際最初に必ず走る処理を定義するconstructorが走ると思っています ・DateクラスのconstructorはDate.prototype.constructorの事だと思っています これらのため、Date.prototype.constructorを変更してからDateクラスのインスタンスを生成した場合、変更後のDate.prototype.constructorが動くのではないかと思った疑問です。 何かかみ合っていないような気がしています。(完全に私の説明不足ですすみません)
Lhankor_Mhy

2019/06/20 06:09

> new Date()した際にインスタンスを生成する際最初に必ず走る処理を定義するconstructorが走ると思っています 回答にも書きましたが、それは違います。new Date() で呼ばれるのは、Date です。
Lhankor_Mhy

2019/06/20 08:21

難しいでしょうか。 > DateクラスのconstructorはDate.prototype.constructorの事だと思っています これも違います。Dateクラスのコンストラクタは、Dateです。 class構文を見ると、クラスの中になにかしら constructor みたいな実体があるように見えますが、あれはただのシンタックスシュガーです。Pythonの__init__のように参照できるものがあるわけではないのです。 誤解を恐れずに言えば、Klass.prototype.constructor は、インスタンス生成時に instance.__proto__.constructor を参照することによって、インスタンスからコンストラクタを参照するためにある、と考えていいと思います。 なので、 > Date.prototype.constructorを変更してからDateクラスのインスタンスを生成した場合、変更後のDate.prototype.constructorが動くのではないか の回答は、「Date.prototype.constructor は関係ないです」になります。
domidomi

2019/06/20 09:59

つまりclass構文のconstructor class Aa { ◆◆◆◆◆◆◆◆ここから◆◆◆◆◆◆◆◆ constructor(){ console.log("hidebu"); } ◆◆◆◆◆◆◆◆ここまで◆◆◆◆◆◆◆◆ } と (prototype | インスタンス).constructor はそもそも何にも関係ないものという認識(使われ方考え方が違うもの)であっていますでしょうか?
Lhankor_Mhy

2019/06/21 00:38 編集

> そもそも何にも関係ないものという認識(使われ方考え方が違うもの)であっていますでしょうか? おおむね、そういうことだと思います。 (細かい話をすれば、インスタンス.constructor ではなくて、インスタンス.__proto__.constructor です。) 参考になるサイトを挙げます。 JavaScript の new 演算子の意味: Days on the Moon http://nanto.asablo.jp/blog/2005/10/24/118564 や...やっと理解できた!JavaScriptのプロトタイプチェーン - maeharinの日記 https://maeharin.hatenablog.com/entry/20130215/javascript_prototype_chain 9.2.2 [[Construct]] ( argumentsList, newTarget) | ECMAScript 2015 Language Specification – ECMA-262 6th Edition https://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
Lhankor_Mhy

2019/06/21 00:50 編集

仕様をよくよく見直してみると、「constructor の実体はない」という私の説明は誤っているようです。内部的にはオブジェクトに[[construct]]内部メソッドが存在し、new演算子がついた場合はそちらが呼び出されているようでした。 不正確な回答をしてしまい、大変失礼しました。 ただ、プログラムコードからその内部メソッドにアクセスする手段はなさそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問