2016-01-19 4 views
12

私はこのようなfn.bind()Mozilla polyfillに参照してください。JavaScriptでfn.bind()をpolyfillすると、なぜ "this"のタイプをチェックする必要がありますか?

if (!Function.prototype.bind) { 

    Function.prototype.bind = function(oThis) { 

    if (typeof this !== 'function') { 
     // closest thing possible to the ECMAScript 5 
     // internal IsCallable function 
     throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 
    } 

    // other code omitted here... 

    }; 
} 

我々はthisの種類を確認する必要があり、なぜ私は理解していない...私たちが言う場合fn.bind()fnが関数であるので、それがしますfnが関数でない場合、fn.bindはプロトタイプの継承によってFunction.prototype.bindに決して到達しません。では、なぜthisのタイプをチェックする必要がありますか?

答えて

8

if fn is not a function, then fn.bind will never reach Function.prototype.bind by prototypal inheritance.

Trueが、しかし、これはthisを設定することができる唯一の方法ではありません。たとえば、bind関数で.callまたは.applyメソッドを使用する場合、またはそれを他のオブジェクトに割り当てるのと同じように本当に狂っている場合は、ネイティブ関数とは異なる動作をします。

var notAFunction = {}; 
 
var someObject = {}; 
 

 
Function.prototype.bind.call(notAFunction, someObject);

これは以下のように、TypeErrorをスローします:

TypeError: Function.prototype.bind called on incompatible Object

この余分なチェックは基本的にエミュレートしているネイティブES5メソッドを使用して、次のコードを考慮

できるだけ緊密にネイティブ関数からこのサニティチェックを行います。


So why do we have to check the type of this ?

あなたはが、この場合は、ほとんどのまともなコードのエッジ場合のように、に持っているが、ポリフィルはES5により、密接に動作させるためには技術的にありませんスペック、それはいいです。 ES5のブラウザはこのコードを実行することさえないので、最新のブラウザではパフォーマンスが低下しません。


この動作is defined in the ECMA-262 5.1 Edition specification以降:

  1. Let Target be the this value.
  2. If IsCallable(Target) is false, throw a TypeError exception.
3

ではない、すべての呼び出し可能オブジェクトから継承する(または等しい)Function.prototype。たとえば:Function.prototypeから継承

typeof document.createElement('object') === "function"; // true 
document.createElement('object') instanceof Function; // false 

とにもオブジェクトがbindは影のかもしれない:

var f = function() {}; 
f.bind = 123; 
f.bind === Function.prototype.bind; // false 

しかし、あなたはそれらの呼び出し可能オブジェクトのFunction.prototype.bindを呼び出すことができるようにしたいことがあります。だから我々はFunction.prototype.callFunction.prototype.applyまたはReflect.applyのようなものを持っている。呼び出し可能であるかどうかにかかわらず、それらを使用して任意のオブジェクトのbindに電話をかけることができます。

逆も可能です。 Function.prototypeから継承し、呼び出し可能ではないオブジェクトを持つことができます。たとえば:

Object.create(Function.prototype) instanceof Function; // true 
typeof Object.create(Function.prototype) === "function"; // false 

したがって、あなたは、任意の仮定をすることはできません。 PolyfillをES5に準拠させるには、オブジェクトが呼び出し可能かどうかをチェックする必要があります。 ES5では、typeof"function"を返すかどうかをチェックするのはまさにそれです(ただし、ES3ではホストオブジェクトでは機能しない可能性があります)。

+0

実際に誰かが 'Function.prototype.bind'をpolyfillする必要があるのであれば、それはES5に完全に準拠していない古いJSエンジンであり、' typeof X === "関数のテストは必ず呼び出し可能。たとえば、IE8では、 'typeof alert'は' 'object" 'です。また、http://stackoverflow.com/questions/17975210 –

+0

@ GOTO0も参照してください。実際、ホストオブジェクトは、特にIEの首の痛みです。 – Oriol

関連する問題