質問: new Date("2016/12/14"); document.write(dat.getFullYear()); //2016 ``` これは換言すれば、組み込みオブジェクトのDateのインスタンスを生成して、その中のgetFullYearプロパティを使いたいのでドットで結んでいるということかと思います。 一方で ``` var num1=100, num2=200; document.write(Math.max(num1,num2)); //200 ``` これは換言すれば、組み込みオブジェクトのMathオブジェクトを使用しており、ただMathオブジェクトは静的プロパティ/メソッドのため、インスタンスを生成できないので、そのmaxプロパティを直接使用していると理解しております。 <ご質問> 1. ここで、一点目の質問ですが、dat.getFullYear()について、この()のなかに、"2016/12/14"としてdat.getFullYear("2016/12/14")としてMathオブジェクトのように引数を書かないのは、これはインスタンスを生成しているからなのでしょうか? 両者が数字をどのような流れで代入して、それぞれの返り値に至っているのかが引数の書き方の観点から分からなかったので、ご教示ください。 2. また上記の1.の結果何らかの理由でインスタンスを生成する場合、特定のプロパティの呼び出しに引数を書かなくても良いとして(ここでいうdat.getFullYear()について、dat.getFullYear("2016/12/14")としなくても良いという意味)末尾の()については、なぜ省略できないのでしょうか?他のオブジェクトと比較した場合、 var str="Hello"; document.write(str.length); のように引数の()が書略可能な場合と不可能な場合は本質的にどういう点で相違しているのか(document.write(str.length())としなくてよい。。?)がまだ理解できないのですが、この点ご教示願えますでしょうか? 何卒、宜しくお願い申し上げます。
回答: ### Date.prototype.getFullYear() が引数を要求しない理由 > > 1. ここで、一点目の質問ですが、dat.getFullYear()について、この()のなかに、"2016/12/14"としてdat.getFullYear("2016/12/14")としてMathオブジェクトのように引数を書かないのは、これはインスタンスを生成しているからなのでしょうか? > > > `Date.prototype.getFullYear()` は `this` 値を元に「年」を算出する為、引数を必要としません。 * 20.3.4.4 Date.prototype.getFullYear() - ECMAScript® 2016 Language Specification ### Date.prototype.getFullYear() の関数呼び出しで括弧を必要とする理由 > > 2. また上記の1.の結果何らかの理由でインスタンスを生成する場合、特定のプロパティの呼び出しに引数を書かなくても良いとして(ここでいうdat.getFullYear()について、dat.getFullYear("2016/12/14")としなくても良いという意味)末尾の()については、なぜ省略できないのでしょうか? > > > `()` を付けるのはそれが関数だからです。 原則として**通常の関数呼び出し時には括弧が必須**です(`new` 演算子で引数を指定しない場合のみ省略可能)。 括弧を付けずに `new Date("2016/12/14").getFullYear` で参照する為には `new Date()` 呼び出し時に「年」を算出して `getFullYear` プロパティを定義しなければなりません。 もしくは `Date.prototype.getFullYear` が getter プロパティとして定義されていなければなりません。 **(2016/12/14 13:39追記)** ちなみに、関数に対して括弧を付けずに参照したら関数オブジェクト自身が返ります。 ``` var date = new Date("2016/12/14"); document.write(date.getFullYear); // function getFullYear() { [native code] } document.write(date.getFullYear()); // 2016 ``` 関数オブジェクトはコールバック関数として利用したり、別の場所へ参照コピーする際に利用できます。 ### プロパティとメソッド(関数) メソッド(関数)は関数呼び出し時に処理を実行して返り値を算出します。 プロパティは基本的には処理を伴いませんが、**getter/setter の例外**があります。 `Array#length` には setter の役割があるため、処理を伴います。 * 22.1.4.1 length - ECMAScript® 2016 Language Specification ``` var a = new Array(1, 2, 3); a.length = 2; // Array#length は要素数が2になるように切り詰める処理を行う console.log(a); // [1, 2] ``` getter/setter は `Object.create`, `Object.defineProperty` でユーザ定義する事が出来ます。 ### Date.prototype.getFullYear の仮想コード ``` function Date (year /* [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ] */) { this.timeValue = ...; // 1970/01/01 00:00:00 からのミリ秒を代入する。this.timeValue は内部プロパティ [[DateValue]] の仮想コードで実際には存在しない。内部プロパティ [[DateValue]] は外部から参照出来ない。 } Date.prototype.valueOf = function valueOf () { return this.timeValue; // 内部プロパティ [[DateValue]] を返す }; Date.prototype.getFullYear = function getFullYear () { return this.timeValue / hogehoge ...; // 内部プロパティ [[DateValue]] を元に「年」を算出する }; ``` ### 更新履歴 * 2016/12/15 08:45 「Date.prototype.getFullYear の仮想コード」を追記 Re: SugiuraY さん