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

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

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

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JavaScript

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

Q&A

解決済

3回答

2014閲覧

fn.apply(ctx, array)とFunction.prototype.apply.call(fn, ctx, array)の違い

kkkke

総合スコア12

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JavaScript

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

0グッド

2クリップ

投稿2016/11/03 11:47

編集2016/11/03 11:52

###前提・実現したいこと

fn.apply(ctx, [1, 2, 3]) //と Function.prototype.apply.call(fn, ctx, [1, 2, 3])

の違いを知りたいです。

ここの説明では
https://ponyfoo.com/articles/es6-reflection-in-depth

If we fear fn might shadow apply with a property of their own, we can rely on a safer but way more verbose alternative.

fnが独自のプロパティで適用シャドウかもしれないと恐れるならば、
安全に、より詳細な代替にすることができる
から

と説明されているようですが、
自分の英語の和訳不足で意味がわかりません。

どのような場合を恐れてFunction.prototype...から記述しているのでしょうか
ユースケースなど事例として教えていただけたら幸いです。

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

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

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

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

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

guest

回答3

0

ベストアンサー

Function.prototype.apply.call

関数が Function.prototype を継承していなくとも TypeError を発生させません。

JavaScript

1function fn () { 2 console.log(arguments); 3} 4fn.__proto__ = null; 5 6Function.prototype.apply.call(fn, null, [1, 2, 3]); // [1, 2, 3] 7fn.apply(null, [1, 2, 3]); // TypeError: fn.apply is not a function

Function.prototype.apply の用途

用途によって呼び出し方も変わるものです。

JavaScript

1function fn () { 2 console.log(arguments); 3} 4 5fn.apply(null, [1, 2, 3]); // [1, 2, 3]

ユーザ定義関数をそのまま呼び出す場合は Function.prototype を継承している事がコード制作者にとって自明なので問題ありません。
しかし、その関数の所在が明らかでない場合、例えば引数で受け取った関数の場合はどうでしょう。

JavaScript

1function hoge (fn) { 2 fn.apply(null, [1, 2, 3]); 3}

この場合、hoge() が呼び出されるまで fn.apply(null, [1, 2, 3]); が実行可能か判断することが出来ません。
それがどんな関数であっても呼び出せることを保証するなら Function.prototype.apply.call で呼び出すのが確実です。

JavaScript

1function hoge (fn) { 2 Function.prototype.apply.call(fn, null, [1, 2, 3]); 3}

コールバック関数

前節では説明を省略しましたが、引数に何らかのアクションをする場合は引数値をテストして例外処理を設けるのが安全な設計です。
私はこの手の問題はESで規定されたビルトイン関数を参考にすることが多いのですが、ここでは Array.prototype.forEach を事例にあげます。

JavaScript

1[1, 2, 3].forEach(null); // TypeError: null is not a function

以下、ES7 (ES2016)より引用します。

22.1.3.10 Array.prototype.forEach ( callbackfn [ , thisArg ] )

  1. Let O be ? ToObject(this value).
  2. Let len be ? ToLength(? Get(O, "length")).
  3. If IsCallable(callbackfn) is false, throw a TypeError exception.

7.2.3 IsCallable ( argument )

  1. If Type(argument) is not Object, return false.
  2. If argument has a [[Call]] internal method, return true.
  3. Return false.

第一引数 callbackfn を Object 型に変換し、[[Call]] を持たない場合に TypeError 例外を発生させます。
同様の処理をしたい場合は次のように書きます。

JavaScript

1function sample (callbackfn) { 2 callbackfn = Object(callbackfn); // Object 型に変換する 3 4 if (typeof callbackfn !== 'function') { // callbackfn が [[Call]] を持たないなら 5 throw new TypeError(callbackfn + ' is not a function'); 6 } 7}

次に Function.prototype.apply を使うケースを想定します。
上記コードを拡張するなら、引数 callbackfnFunction.prototype を継承しているかを判定すればいいでしょう。

JavaScript

1function sample (callbackfn, _arguments) { 2 callbackfn = Object(callbackfn); // Object 型に変換する 3 4 if (typeof callbackfn !== 'function') { // callbackfn が [[Call]] を持たないなら 5 throw new TypeError(callbackfn + ' is not a function'); 6 } 7 8 if (!(callbackfn instanceof Function)) { 9 throw new Error(callbackfn ' must be an instance of Function'); 10 } 11 12 callbackfn(_arguments); 13}

ただし、iframe等、異なる所属のドキュメント上で生成された関数に対して上記コードは期待通りに動作しないので厳密性を上げるにはもう少し手を入れる必要があります。

JavaScript

1if (!(callbackfn instanceof Function) || Object.prototype.toString.call(callbackfn) !== '[object Function]' || ) { 2 throw new Error(callbackfn ' must be an instance of Function'); 3}

ここまで説明しておいて何ですが、実際にはここまで書くことはありません。
ECMAScript には [[Call]] を持たない値に対して関数呼び出ししようとした場合に TypeError 例外を返す仕様があるからです。

JavaScript

1function sample (callbackfn, _arguments) { 2 callbackfn = Object(callbackfn); // Object 型に変換する 3 4 callbackfn(_arguments); // [[Call]] を持つ値にたいして関数呼び出しを実行する 5} 6 7sample(null); // TypeError: callbackfn is not a function

そして、Function.prototype.apply にも [[Call]] が存在しない場合に TypeError 例外を発生させる規定があります。

19.2.3.1 Function.prototype.apply ( thisArg, argArray )

  1. If IsCallable(func) is false, throw a TypeError exception.

従って、Object 型への型変換処理を除けば次のように書けます。

JavaScript

1function sample (callbackfn, _arguments, thisArg) { 2 return Function.prototype.apply.call(callbackfn, thisArg, _arguments); 3} 4 5function callbackfn1 () { 6 console.log(arguments); 7} 8 9sample(callbackfn1, [1, 2, 3]); // [1, 2, 3] 10sample.__proto__ = null; 11sample(callbackfn1, [1, 2, 3]); // [1, 2, 3] ([[Prototype]] が Function.prototype でなくとも実行できる) 12sample({}); // TypeError: Function.prototype.apply was called on #<Object>, which is a object and not a function 13sample(null); // TypeError: Function.prototype.apply was called on null, which is a object and not a function

getElementById.apply()

jQuery に影響されてか次のようなショートカット関数をたまに見かけます。

JavaScript

1function $ (id) { 2 return document.getElementById(id); 3}

このコードには document が現在のページの document に固定されているという問題があります。
iframe要素、DOMParser で生成、window.open 等、他の所属の document も指定できたり、任意の要素ノードを指定できる方が汎用性が高まるでしょう。

JavaScript

1function $ (id, node) { 2 var getElementById = document.getElementById, 3 _arguments = Array.prototype.slice.call(arguments); 4 5 _arguments = [id].concat(_arguments.slice(2)); // 第二引数を取り除いた引数リストを生成する 6 7 if (Object(node) !== node || !('nodeType' in node) || typeof node.getElementById !== 'function') { // Object 型ではない、もしくは nodeType プロパティを持たない、もしくは getElementById プロパティが [[Call]] を持たないなら 8 node = document; 9 } 10 11 return getElementById.apply(node, _arguments); 12} 13 14console.log($('hoge')); 15console.log($('hoge', document)); // 任意の this 値を指定できる 16console.log($('hoge', document, 1, 2)); // document.getElementById('hoge', 1, 2) と等価 (将来的に getElementById が第二引数以降を持つようになっても対応できる) 17 18document.getElementById.__proto__ = null; // [[Prototype]] に Function.prototype がセットされていない状態にする 19console.log($('hoge')); // TypeError: getElementById.apply is not a function 20console.log($('hoge', document)); // TypeError: getElementById.apply is not a function 21console.log($('hoge', document, 1, 2)); // TypeError: getElementById.apply is not a function

getElementById は DOM 規定のAPIですが、DOM がJavaScript 以外も考慮されたAPIという事もあってか [[Prototype]] に Function.prototype が存在する事を保証していません。
多くの実装では document.getElemehtById.apply が期待通りの動作するよう実装されていますが、仕様にない以上、次のように Function.prototype を継承していない実装がある可能性があります。

JavaScript

1document.getElementById.__proto__ = null; // [[Prototype]] に Function.prototype がセットされていない 2document.getElementById.apply(document, ['hoge']); // TypeError: document.getElementById.apply is not a function

前節と同様、Function.prototype.apply を直接呼び出せば安全に実装できます。

function $ (id, node) { var getElementById = document.getElementById, _arguments = Array.prototype.slice.call(arguments); _arguments = [id].concat(_arguments.slice(2)); // 第二引数を取り除いた引数リストを生成する if (Object(node) !== node || !('nodeType' in node) || typeof node.getElementById !== 'function') { // Object 型ではない、もしくは nodeType プロパティを持たない、もしくは getElementById プロパティが [[Call]] を持たないなら node = document; } return Function.prototype.apply.call(document.getElementById, node, _arguments); } document.getElementById.__proto__ = null; // [[Prototype]] に Function.prototype がセットされていない状態にする console.log($('hoge')); console.log($('hoge', document)); // 任意の this 値を指定できる console.log($('hoge', document, 1, 2)); // document.getElementById('hoge', 1, 2) と等価 (将来的に getElementById が第二引数以降を持つようになっても対応できる)

更新履歴

  • 2016/11/06 12:00 コールバック関数、Function.prototype.apply, getElementById...etc の説明を追加

Re: kkkke さん

投稿2016/11/03 12:12

編集2016/11/06 03:00
think49

総合スコア18156

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

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

kkkke

2016/11/03 12:17 編集

なるほど!!prototypeオブジェクトに意図しない代入で辿れなくなった際ですね!ありがとうございます!!
think49

2016/11/03 23:36 編集

__proto__ に意図しない値が代入されるケースを考慮して、というのもありますが、Function.prototype を継承していないネイティブ関数がある可能性も考慮されています。 ECMAScript の全てのビルトイン関数は Function.prototype を継承する事を保証していますが、他の仕様では保証しているとは限りませんので。 例えば、DOM 規定の getElementById は Function.prototype を継承する事を保証していませんので Function.prototype.apply を呼び出せない実装がある可能性があります。 同様に全ての Object 型が Object.prototype を継承する事も保証されていない為、obj.hasOwnProperty('hoge') ではなく、Object.prototype.hasOwnProperty.call(obj, 'hoge'); と書く場合があります。
kkkke

2016/11/04 01:38

詳細な説明ありがとうございます。 > DOM 規定の getElementById は Function.prototype を継承する事を保証していませんので Function.prototype.apply を呼び出せない実装がある可能性があります。 すみません。ここがイマイチわかりません。 document.getElementByIdをapplyで呼ぶことがないと思っていたので。。 > Object 型が Object.prototype を継承する事も保証されていない為、obj.hasOwnProperty('hoge') ではなく、Object.prototype.hasOwnProperty.call(obj, 'hoge'); と書く場合があります。 Object型はJavaScriptの仕様のビルドインオブジェクトの中の基本オブジェクトというものではないのですか?? https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects hasOwnPropertyは持っていないケースがあるのですか?? 全てのメソッドを下のように String.prototype.slice.call(str,1, "" ) 使ったほうが安全のように聞こえるのですが、、 ネイティブ関数を検索しましたが、記事が見つかりません。 ネイティブ関数というのはどのようなもののことを言いますか??詳細、もしくはここを参照にして!というところがあればお願いします。
kkkke

2016/11/04 12:08 編集

上記の ネイティブ関数とは何かは そもそもホストオブジェクト、ネイティブオブジェクト、ビルドインオブジェクト を理解する必要があり、 仕様書や良記事から調べてぼんやりしていた部分がわかりました。 以下理解したことです。 =========================================== 【ホストオブジェクト】 WebブラウザなどのJavaScript実行環境がもつ複数のオブジェクト。 JavaScript言語仕様とホストオブジェクトの間には何の関係がない。ECMAScirptの一部ではない Webブラウザが提供するものなので以下はIEとChromeで違う for (x in window){ console.log(x) } nativeでないオブジェクトをまとめてhostオブジェクトという。 ホームパーティのホストというように場所を提供するという意味もあり、 JavaScriptが実行できる場所(ブラウザ)がホストで、そのホストが提供するオブジェクト Window、Location、Document等がhostオブジェクトの代表 それらはDOM仕様書としてJavaScriptとは別に定義されていて、 それらをJavaScriptの仕様書の中で見つけることはできない。 つまりnativeではない nativeオブジェクトでないどんなオブジェクトもhostオブジエクト =========================================== 【native object】 ホスト環境によるというよりJavaScript仕様書で十分に定義されたECMAScript実装内のオブジェクト 標準ネイティブオブジェクトは仕様書で定義されている。 多くのネイティブオブジェクトはbuild-in 他のものはECMAScriptプログラムの実行の過程の間で構成されたもの。 =========================================== 【built-in object(特に重要なnativeオブジェクト/組み込みオブジェクト)】 ECMAScript実装によって提供されたObjectで、ホストオブジェクトから独立している ECMAScriptプログラムの実行時に贈られている Object、Function、Boolean、String、等のnativeオブジェクトが代表的なbuild-inオブジェクト ほとんどのbuild-inオブジェクトはfunctionでcallできる =========================================== このことからnative関数はnativeオブジェクトが持つ関数ということがわかりました。 ただやはりthink49さんがおっしゃっている この2点がわかりません。 ↓ 1、 DOM 規定の getElementById は Function.prototype を継承する事を保証していませんので Function.prototype.apply を呼び出せない実装がある可能性があります。 2、 Object 型が Object.prototype を継承する事も保証されていない為、obj.hasOwnProperty('hoge') ではなく、Object.prototype.hasOwnProperty.call(obj, 'hoge'); と書く場合があります。 1は、 自分の理解ではDOM仕様内のgetElementByIdでそもそもapplyを呼ぶことはできないのではないかと思います。 2は、 var obj = {}で、objはprototypeを持っていると思っています。(prototypeに代入されていない限り)これが生成時から保障されないのはどんな時でしょうか。 繰り返しますが、もしネイティブ関数が安全でないなら 全てを下のように String.prototype.slice.call(str,1, "" ) 呼ぶ方がいいことにならないのでしょうか。 もし何かご存知の方お教えください。
think49

2016/11/04 12:26

JavaScriptは複数の仕様書から構成される珍しい言語ですが、基本となる仕様に ECMAScript があります。 ネイティブ関数は ECMAScript 3 (以降、ES3 と表記する)仕様定義のものとして記載しています。 http://www2u.biglobe.ne.jp/~oz-07ams/2002/ecma262r3/4_Overview.html#section-4.3.6 ES6以降は用語定義が変わっているようですが、それは置いておきます。 http://www.ecma-international.org/ecma-262/7.0/#sec-terms-and-definitions おおまかに説明すれば、ビルトイン関数(ES定義の関数)、ネイティブ関数(ブラウザが予め用意している関数、ビルトイン関数を含む)です。 関数が Function#apply を使うためには該当関数 fn において fn.__proto__ === Function.prototype が成立しなければなりません。 例えば、(function () { console.log(arguments); }.apply([1, 2, 3])); が成立するのは関数式の生成時に関数の [[Prototype]] に Function.prototype をセットする事が仕様で定められているからです。 http://www2u.biglobe.ne.jp/~oz-07ams/2002/ecma262r3/13_Function_Definition.html#section-13.2 getElementById は DOM 規定ですので、document.getElementById.apply(document, ['hoge']) を成立させるには DOM の仕様書で getElementById の [[Prototype]] に Function.prototype がセットされるという記述がある必要があります。 DOM Standard (DOM4) https://dom.spec.whatwg.org/ にそれらしき記述はありません。 DOM Level 3 Core に [ECMAScript Language Binding] の付録がありますが、 https://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html にもそれらしき記述がありません。 従って、DOM を実装するブラウザが document.getElementById.__proto__ === Function.prototype を成立するように実装する必然性はない、という事になります。 最も、多くの技術者が関数の [[Prototype]] に Function.prototype を期待することは容易に想像できるのでブラウザ開発者も同様の発想でよきにはからってくれます。 「仕様に厳格であるなら」そういう考え方も出来る、という事です。 > Object型はJavaScriptの仕様のビルドインオブジェクトの中の基本オブジェクトというものではないのですか?? Object 型はあくまで「型」の一種であってビルトインオブジェクトとは限りません。 document.getElementById('hoge') や document.querySelectorAll('p') のような ES 規定外のオブジェクトまではコントロールできません。 また、ES 範囲内であっても Object.create(null) で Object.prototype を継承しない Object 型を生成する事が可能です。 最近では new Map が出来ましたが、Object.prototype 上のプロパティを期待しないマップオブジェクト的な使い方をする場合に Object.create(null) が利用される場合があります。
kkkke

2016/11/04 13:11 編集

ご説明ありがとうございます。 多分この説明で「なるほどそうか!」と納得する方は多くないのではないでしょうか。 DOM仕様のオブジェクトまでの影響範囲というよりは ES仕様内での安全性の話で大丈夫です。 (リンクまでいただきありがとうございます。全ての箇所は調べ尽くします) それでいうとObject.create(null)の話は身近でわかりやすかったです。 これは最初に自分が開眼したプロパティを辿れなくなるから(意図的に第一引数に渡したとはいえ)というのと同じ意味合いかなと思っています。 仕様上厳格にはできる。 というのも大事なのですが、 それより優先的に理解したいのは よく使われている Array.prototypeなんちゃらやStoring.prototypeなんちゃらなどです。 これは多分自分以外の方もそう思っているのではないかと思います。 で__proto__上にそのメソッドがある保障がないというのは理解しました。 で、 保障がないなら、(先ほど回答いただいた説明の通り、いろいろな場合が想定されるなら) 全てのメソッドは下のように String.prototype.slice.call(str,1, "" ) 使ったほうが安全のように聞こえるのですがそれについてはいかがですか??
kkkke

2016/11/05 02:06 編集

ここのページで出てくる「ネイティブ関数」という言葉は造語ではないか?Build-inObjectが持つ関数ではないか?」という回答を頂きました。 https://teratail.com/questions/54028 自分もそう思います。 現時点での仕様書にはないので「その言葉は廃止」されたのだと思います。 ご回答いただいた方も >ネイティブ関数は ECMAScript 3 (以降、ES3 と表記する)仕様定義のものとして記載しています。 >http://www2u.biglobe.ne.jp/~oz-07ams/2002/ecma262r3/4_Overview.html#section-4.3.6 >ES6以降は用語定義が変わっているようですが、それは置いておきます。 おっしゃっていましたが、 この場合「置いておく」のはES3の方で、 最新仕様からの説明の方がありがたかったなというのが感想です笑 勉強にはなりました笑 付随した疑問にはなってしまいましたが、 ネイティブ関数 / オブジェクトに関しては解決しました。
kkkke

2016/11/05 14:39 編集

なんだろ、 疑問点から疑問点を生み出してごちゃごちゃに混乱させて、 答えないって不誠実ですね。 あとは自分で調べて!ってゆーのはもちろんなのですが、腑に落ちません。 一回解決したのに(ベストアンサーにも一度しましたが2回目の該当ユーザーの回答で外させていただきました。多くのこれを見た方がかえってわからなくなったと思ったので) 上記にあるようにさらに疑問点生みだして、去る。 この文章をみて混乱している方は多いと思います。 「質問にする」で今一度そこだけ公に質問してもいいのですが ここの流れで回答を得た方が他の方もわかりやすいと思うのでそうしています。 今解決できないのは下記の部分です。 =========================== 全てのメソッドを下のように String.prototype.slice.call(str,1, "" ) 使ったほうが安全のように聞こえるのですがなぜ多くの記述はそうじゃないのでしょうか? 「記述が冗長だから、this参照を渡せる、第二引数にその引数を渡せる」 と 「__proto__で辿れないリスク」なら後者を選ぶと思うのですが。
think49

2016/11/06 03:53

> Array.prototypeなんちゃらやStoring.prototypeなんちゃらなどです。 > String.prototype.slice.call(str,1, "" ) それが関数である事が明確なケースだと判断した為、applyコードでは説明を省きましたが、本来は変数値に対して正当性検査してそれが期待通りに動作するように工夫するはずです。 その変数がどのような過程を経てそこに存在するのか、想像してみれば答えは出てくるであろうと考えます。 回答内容を編集しました。 > 【native object】 別スレッドで回答しました。 > 疑問点から疑問点を生み出してごちゃごちゃに混乱させて、答えないって不誠実ですね。 別スレッドで回答しました。
kkkke

2016/11/06 06:51

> 更に補完するなら tyoeof 演算子では "object" を返す値を「ネイティブかつ [[Call]] を持つもの」と定義しています。 http://ecma-international.org/ecma-262/5.1/#sec-11.4.3 Object (native and does not implement [[Call]]) not implement call実装をしないもののようです。
guest

0

いろいろと私への不満が募っているようですが、私もあなたに伝えたいことが山ほどあります。

質問者に伝えたいこと

  • 私にも生活リズムがあり、余裕の出来た空き時間に回答しているという事実を理解していますか
  • 私が回答にどれぐらいの時間を割いていると思っていますか
  • "多分この説明で「なるほどそうか!」と納得する方は多くないのではないでしょうか" と仰いますが、仕様書とはすぐに理解できるような簡単なものではありません。私は英文の仕様書なら1節を読み解くのに1日かけてもわからず、1週間ぐらいかけて読み解く場合がざらにあります。ですので、「最新仕様がいい」と気軽に言われてもそう簡単には読めません。勿論、最新仕様が一番いいのは分かります。ですが、それを読み解く労力を想像して下さい。)。
  • 30分~1時間置きに返信を追加していますが、回答内容を読解する時間をどれだけかけていますか。
  • 最新仕様(ES7)をお望みのようですが、私が掲示した 4.3 Terms and Definitions - ECMAScript® 2016 Language Specificationを読み解こうと努力をしましたか。読み解こうとしたならあなたはどの記述を読んでどんな解釈をしましたか。
  • 初心者だからと甘えていませんか。初心者が分からないのは当然ですが、理解する為の自助努力を放棄して「他人に聞いた方が早い」と安易に考えていませんか。「理解するための手段が分からない」のなら分かりますが、理解する為の手段がありながら(仕様書のURLが分かっている)それをしないのは問題とは思いませんか。
  • teratail をどのような場だと思っていますか。質問するときのヒント|teratail(テラテイル)を読みましたか。「まず、出来るだけ自分で調べてみる。」「調べてみてわからなかったら調べた内容を具体的に書き、自分の解釈を具体的に説明して意見を求める」teratailとはそんな場だと私は考えます。

簡単な質問/難しい質問

「上級者なら初心者の質問ぐらいは簡単に記憶から引っ張り出せるはず」
そんな風に考えているのかもしれませんが、上級者だって全てを記憶しているわけではなく、調べものぐらいします。
(私が上級者というわけではありません。物のたとえであって私よりも知識がある方はここにはたくさんいらっしゃいます。
今までに私の間違った回答をすれば指摘を頂いた事が何度もあります。)

簡単なように見えて難しい質問もあります。
特に仕様であるなら不正確な事はいいたくありませんので、該当部分を引用しながら仕様を読み直して説明します。
割と気軽に深い部分を質問する方はいるのですが、調べる作業を丸投げしているように感じます。
本来は質問者が出来るだけ調べてわからない点があれば該当部分を引用し、自分の解釈を述べ、分からない部分を具体化する質問であってしかるべきだと私は考えます。

Re: kkkke さん

投稿2016/11/06 03:06

think49

総合スコア18156

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

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

0

[ES3-7] ビルトインオブジェクト(built-in object) とネイティブオブジェクト(Native Object)

ビルトインオブジェクトとは ECMAScript で規定されるオブジェクトの総称です。

ES7 ではビルトインオブジェクトから関数だけを抽出して**ビルトイン関数(built-in function)**が定義されています。

ES3, ES5.1 ではネイティブオブジェクト(Native Object)が定義されています。
(ES7 にはなく、別の用語が定義されています)

ECMAScript 5.1

以下、ECMAScript 5.1 仕様の記述を引用します。

4.3.7 built-in object
object supplied by an ECMAScript implementation, independent of the host environment, that is present at the start of the execution of an ECMAScript program
NOTE: Standard built-in objects are defined in this specification, and an ECMAScript implementation may specify and define others.
Every built-in object is a native object.
A built-in constructor is a built-in object that is also a constructor.
Every built-in object is a native object.

以下、『<a href="http://ecma262.info/">ECMA-262 Edition 5.1を読む</a>』より引用。
「4.3.7 組み込みオブジェクト(built-in object)
ホスト環境ではなく、ECMAScript実装によって提供されるオブジェクト。ECMAScriptプログラムを開始した時点で存在している。
NOTE: 標準の組み込みオブジェクトは本仕様で定義されている。ECMAScript実装では、他の組み込みオブジェクトを指定し、定義する事がある。組み込みオブジェクトは全てネイティブオブジェクトである。組み込みコンストラクタとはコンストラクタでもある組み込みオブジェクトの事である。」

4.3.6 native object
object in an ECMAScript implementation whose semantics are fully defined by this specification rather than by the host environment
NOTE: Standard native objects are defined in this specification. Some native objects are built-in; others may be constructed during the course of execution of an ECMAScript program.

以下、『<a href="http://ecma262.info/">ECMA-262 Edition 5.1を読む</a>』より引用。
「4.3.6 ネイティブオブジェクト
ホスト環境ではなく、本仕様によってセマンティクスが完全に定義されるECMAScript実装のオブジェクト。
NOTE: 標準のネイティブオブジェクトは本仕様で定義されている。ネイティブオブジェクトには組み込みオブジェクトとして提供されるものと、ECMAScriptプログラムの作成時に生成されるものがある。」

4.3.8 host object
object supplied by the host environment to complete the execution environment of ECMAScript
NOTE: Any object that is not native is a host object.

以下、『<a href="http://ecma262.info/">ECMA-262 Edition 5.1を読む</a>』より引用。
「4.3.8 ホストオブジェクト
ECMAScript の実行環境を補完する為にホスト環境によって提供されるオブジェクト。
NOTE: ネイティブでないオブジェクトは全てホストオブジェクトである。」

これらの説明はネイティブオブジェクトがビルトインオブジェクトより広義である事を表しています。
そして、ビルトインオブジェクトはECMAScriptプログラムを開始した時点で存在しているものですが、DOM既定の要素ノードオブジェクト等はECMAScfiptプログラムの外側で定義されているのでこれに該当しません。
では、ネイティブオブジェクトとホストオブジェクトの2択になるわけですが、ここでいうホスト環境とはおそらくOSやブラウザを表していると思われます。
DOMオブジェクトはOS/ブラウザ特有のオブジェクトではないので「ネイティブオブジェクト」であろうと判断できます。
更に補完するなら tyoeof 演算子では "object" を返す値を「ネイティブかつ [[Call]] を持たないもの」と定義しています。

JavaScript

1console.log(typeof document.createElement('p')); // "object"

従って、p要素ノードはネイティブオブジェクトと判断できます。

Re: kkkke さん

投稿2016/11/06 03:02

編集2016/11/06 23:15
think49

総合スコア18156

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

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

think49

2016/11/06 03:44

> 【native object】 > ホスト環境によるというよりJavaScript仕様書で十分に定義されたECMAScript実装内のオブジェクト 「JavaScript仕様書」とは何でしょう。 Netscape全盛期にはNetscapeが持つ「JavaScript仕様書」が存在したようですが、今「JavaScript仕様書」といわれるものが何か、私は知りません。 > 多くのネイティブオブジェクトはbuild-in 「多くの」の割合が不明ですが、ネイティブオブジェクトはビルトインオブジェクトを含みます。 > 【built-in object(特に重要なnativeオブジェクト/組み込みオブジェクト)】 > > ...中略... > ほとんどのbuild-inオブジェクトはfunctionでcallできる ほとんどの割合が不明ですが、ビルトインオブジェクトは関数ではありません。 ビルトインコンストラクタやビルトイン関数は関数呼び出し可能です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問