当前位置: 动力学知识库 > 问答 > 编程问答 >

prototypal inheritance - If we polyfill fn.bind() in JavaScript, why do you have to check the type of "this"?

问题描述:

I see in the Mozilla polyfill of fn.bind() like 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...

};

}

I don't understand why we have to check the type of this... because if we say fn.bind() and fn is a function, then it will work, and if fn is not a function, then fn.bind will never reach Function.prototype.bind by prototypal inheritance. So why do we have to check the type of this?

网友答案:

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

True, however this is not the only way this could be set. For example, if we were to use the .call or .apply methods on the bind function itself, or do something really crazy like assign it to other objects, it would behave differently from the native function.

Considering the following code using the native ES5 method:

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

Function.prototype.bind.call(notAFunction, someObject);
网友答案:

Not all callable objects inherit from (or are equal to) Function.prototype. For example:

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

And even objects which inherit from Function.prototype could have bind shadowed:

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

However, you may want to be able to call Function.prototype.bind on those callable objects. That's why we have things like Function.prototype.call, Function.prototype.apply or Reflect.apply. You can use those to call bind on any object, whether it's callable or not.

The inverse is also possible. You can have an object which inherits from Function.prototype and is not callable. For example:

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

Therefore, you can't make any assumption. If you want the polyfill to conform to ES5, you must check whether the object is callable. In ES5, checking whether typeof returns "function" does exactly that (but in ES3 it might not work for host objects).

分享给朋友:
您可能感兴趣的文章:
随机阅读: