Math オブジェクトにはプロトタイプ プロパティはありませんが、コンストラクタ プロパティはあります。コンストラクターの再定義が役立つ場合はありますか?
8 に答える
Math
オブジェクト (正確には、ECMAScript グローバル オブジェクトのプロパティの初期値によって参照されるオブジェクトMath
) にはプロパティがありません。ECMAScript言語仕様、5.1 版、セクション 15.8「数学オブジェクト」constructor
を参照してください。したがって、
Math.hasOwnProperty("constructor")
を返しますfalse
(ECMAScript Ed. 3 以降の適合する実装で)。
Math
オブジェクトは、そのプロトタイプからプロトタイプ チェーンを介してプロパティを継承します。constructor
これは、「標準の組み込みオブジェクト プロトタイプ オブジェクト (15.2.4)」(同上) であり、Object.prototype
プロパティによって最初に参照されたものと同じです。後者のオブジェクトは、(上記参照) のようないくつかの便利なプロパティを提供しますObject.prototype.hasOwnProperty
。Math
そのため、代わりにオブジェクトのプロトタイプ チェーンが空でないことは理にかなっています。
Math
オブジェクトも継承するというObject.prototype.constructor
ことは、ECMAScript 実装におけるその無条件継承の副作用にすぎません (Edition 4 提案の実装、およびおそらく将来の Edition の実装を除いて) プロパティにはそれを防ぐための適切な可視性修飾子がありません (private
いくつかのクラスベースの言語で)。そしてもちろん、Object
同じプロトタイプから継承するインスタンスのコンストラクターはObject
、グローバル オブジェクトのプロパティの初期値によって参照されるオブジェクトです。だからそれObject.prototype.constructor
を反映する必要があります。そこで、評価した結果
Math.constructor === Object
ですtrue
。
All objects have a constructor
property, which indicates the constructor that created the object.
Even ({}).constructor
returns Object()
.
実際、Math には独自の「コンストラクター」プロパティがありません。これは、「toString」、「hasOwnProperty」、および Object.prototype の他のすべてのプロパティを継承するのと同様に、Object.prototype から「コンストラクタ」を継承します。
数学の場合、「構造」はおそらくほとんど役に立ちません。JavaScript の継承がどのように機能するかの結果として存在します。
Math
Object
オブジェクトは(意味Math.__proto__ === Object.prototype
)から「継承」します
このMath
オブジェクトは、どの JavaScript プログラマーにとっても「特別な」ものにすぎませんがObject
、実装と構築が自動化され、隠されているメソッドが添付されたシンプルなものです。
Object.prototype
フィールドを定義し.constructor
ます (実際には、関数はそれ自体を独自のプロトタイプのコンストラクターに割り当てます。ex1を参照してください)
ex1 (ちょっと寄り道) :
function xxx() { }
// then:
xxx.prototype.constructor === xxx; // true
// since xxx is a function:
xxx.constructor === Function.prototype.constructor; // true
// and as such:
xxx.constructor === Function; // true
を使用する場合はMath.constructor
、Math
オブジェクトのプロトタイプ チェーンを次のように検索するだけです (...まあまあのようなものです)。
Math
-->Math.hasOwnProperty('constructor')
=== false
見つかりません 次へ移動
Math.__proto__
-->Math.__proto__.hasOwnProperty('constructor')
=== true
見つかった、戻る:
Math.__proto__.constructor
だから基本的に:
Math.constructor === Object.prototype.constructor; // true
// and as such:
Math.constructor === Object; // true
// and as stated at the top:
Math.__proto__ === Object.prototype; // true
これが役立つことを願っています -ck
MDN言います:
他のグローバル オブジェクトとは異なり、Math はコンストラクタではありません。Math のすべてのプロパティとメソッドはstaticです。
他の言語では、クラスが静的な場合、そのクラスのインスタンス ( オブジェクト ) を作成せずに、そのプロパティとメソッドを直接使用できます。Math コンストラクターが使用される場合、プリミティブ型 (Number、String、Boolean) とは異なり、オブジェクトをサポートするネイティブ型はありません。それらは、ラッパーを使用してオブジェクトに変換できます。
さらに、ルート オブジェクトを拡張することは悪い習慣です。将来、新しい機能が環境に実装され、コードにこれに対するフェールセーフ チェックがない場合は、ネイティブのものをオーバーライドします。
私の個人的な意見では、コンストラクターもプロトタイプも作成しません。独自の数学関数を定義できます。ここでの Math オブジェクトは、標準関数を提示するためだけのものであり、たとえばプログラマーがPi
orを定義しないようにするためのものです。E
また、おそらくユーザー定義の数学関数は、組み込み関数よりも数倍遅くなります。
私の意見では、JavaScript の Math オブジェクトは、他の一般的なプログラミング言語 (Java など) の静的な Math 動作をシミュレートしようとします。これは JavaScript でのみシミュレートでき、すべてのオブジェクトにはデフォルトでプロトタイプとコンストラクターのプロパティがあるため、開発者はコンストラクターのプロパティを に設定するのを忘れてundefined
、Math.constructor = undefined;
グローバル スコープを汚染せずに変換テーブルを生成する必要がある状況では、これが役立ちます。例えば:
Math.constructor = function() {
var i = 0, unicode = {}, zero_padding = "0000", max = 9999;
//Loop through code points
while (i < max) {
//Convert decimal to hex value, find the character, then pad zeroes to the codepoint
Math.constructor[String.fromCharCode(parseInt(i, 16))] = ("u" + zero_padding + i).substr(-4);
i = i + 1;
}
}
コンストラクターを呼び出して、次のように入力します。
Math.constructor();
Math.constructor["a"]
もう 1 つの用途は、プロパティとメソッドを拡張して、グラフ ライブラリのプリミティブを定義することです。
root(arg,index) "index-th" 引数のルート。例: root(x,6) x の 6 番目のルート、root[tan(x),4] x のタンジェントの 4 番目のルート。 sqrt() 引数の平方根 (括弧内の数値または式)。root(引数,2)と同等 cbrt() 引数の立方根。root(引数,3)と同等 logn(arg,base) arg の底-底の対数。 ln() 引数の自然対数 (E を底とする引数の対数 E はオイラー定数) lg() 引数の 10 を底とする対数。logn(argument,10) と同等です。 lb() 引数の底 2 の対数。 exp() 指数関数 E の引数のべき乗、E^argument と同等 sin() 引数のサイン cos() コサイン tan() タンジェント cot() コタンジェント sec() 引数のセカント、同等。1/cos(arg) へ。 csc() コセカント、同等。1/sin(arg) に。 asin() 逆正弦 acos() 逆余弦 atan() 逆正接 acot() 逆余接 asec() 逆正割、逆正割。 acsc() 逆余割、逆余割。 sinh() 双曲線正弦、正弦双曲線 cosh() 双曲線余弦、双曲線余弦 tanh() 双曲線正接、正接双曲線 coth() 双曲線余接、余接双曲線 sech() 双曲正割、Secans 双曲線。 csch() 双曲線コセカント、双曲線コセカン。 asinh() 面積正弦、面積正弦双曲線、逆 sinh()。 acosh() 面積コサイン、面積余弦双曲線、逆 cosh()。 atanh() 面積接線、双曲線面積接線、逆 tanh()。 acoth() 面積余接、面積余接双曲線、逆 cotanh()。 asech() 面積割、面積割双曲線、逆 sech()。 acsch() 面積コセカント、面積コセカン双曲線、逆 csch()。 gaussd(x,mean,sigma) ガウス分布 (「ベル曲線」)。ちなみにgaussd(x,0,1)は「平均値=0、標準偏差=1の正規分布密度」という特殊なケースです。 min(arg1,arg2) 2 つの引数のうち小さい方を返します max(arg1,arg2) 2 つの引数のうち大きい方を返します round() 引数を最も近い整数に切り上げまたは切り下げます floor() arg を切り捨てます。 ceil() arg を切り上げます。 abs() または | | | 引数の絶対値。例: 2abs(sin[x]) または 2|sin(x)| . sgn() 符号関数。
rand 0 と 1 の間の乱数。例: pi*rand*sin(x) または Pirandsin(x) . E オイラー定数 2.718281828459045... LN2 2 の自然対数は 0.6931471805599453... LN10 10 の自然対数は 2.302585092994046... LOG2E E の 2 を底とする対数 (E: 上記を参照)、1.4426950408889633... LOG10E E の 10 を底とする対数、0.4342944819032518... PHI 黄金比 1.61803398874989... PI 3.141592653589793... SQRT1_2 1/2 の平方根は 0.7071067811865476... SQRT2 2 の平方根は 1.4142135623730951...
参考文献
<script type="text/javascript">
Math.prototype=Math;
Math.prototype.rand=function(min,max){
return Math.floor((Math.random() * (max-min+1))+min)
}
var o=[];
for(var i=0;i<100;i++)o.push(Math.rand(-1,1));
alert(o.join(", "))
</script>
粗いこともできます:
Math.rand=function(min,max){
return Math.floor((Math.random() * (max-min+1))+min)
}
Math が Array や String のような独自のプロトタイプを持たない理由は、Math が関数ではなくオブジェクトであるためです。String()
newと newを使用できるので、 と も使用できArray()
ます。String.prototype
Array.prototype
についても同様ですObject, Function, Number, Date, RegExp and even Boolean
。ただし、定義された関数にはプロトタイプ プロパティが割り当てられ、Function および継承する必要があるチェーン内の他のものから継承されます。
関数のように扱いたい場合Math
は、変数を関数でオーバーライドするだけです。その方法Math.constructor
は、オブジェクトを作成したユーザー定義関数に実際にリンクされるため、呼び出されたときに Object を返しません。
最初にネイティブ オブジェクトのコピーを作成してから、それをオーバーライド関数のプロトタイプ プロパティの 1 つに放り込むか、カプセル化を使用して、新しい Math 関数だけがネイティブ メソッドにアクセスできるようにすることができます。この件について他に何が言えるかわかりません。
冒頭の質問はちょっと無意味です。Math.constructor は Object を返し、Object を直接呼び出すのと同じになります。唯一の違いは、コンストラクターを変更した場合です。
とにかくコンストラクタを変更したいのはなぜですか?
オブジェクトはMath
そのままで問題ありません。それがどこかから何かを継承することを期待するとしたら、this
とにかく " " が何を指していると期待するでしょうか? その質問に対する答えを思いつくことができれば、コード化できる目的を持ったものを手に入れることができます。