简体   繁体   English

如果我们在JavaScript中填充fn.bind(),为什么还要检查“this”的类型?

[英]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: 我在fn.bind()Mozilla fn.bind()看到如下:

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. 我不明白为什么我们要检查的类型, this ......因为如果说fn.bind()fn是一个函数,那么它会工作,如果fn不是一个函数,然后fn.bind会永远不会通过原型继承到达Function.prototype.bind So why do we have to check the type of this ? 那么,为什么我们要检查的类型this

if fn is not a function, then fn.bind will never reach Function.prototype.bind by prototypal inheritance. 如果fn不是函数,则fn.bind永远不会通过原型继承到达Function.prototype.bind

True, however this is not the only way this could be set. 诚然,但是这不是唯一的方法this可以设置。 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. 例如,如果我们使用.call.apply方法上的bind功能本身,或者做一些真正疯狂的喜欢它分配给其他的对象,它会从本地函数表现不同。

Considering the following code using the native ES5 method: 使用本机ES5方法考虑以下代码:

 var notAFunction = {}; var someObject = {}; Function.prototype.bind.call(notAFunction, someObject); 

This will throw a TypeError , like the following: 这将抛出TypeError ,如下所示:

TypeError: Function.prototype.bind called on incompatible Object TypeError:在不兼容的Object上调用Function.prototype.bind

This extra check is basically emulating this sanity check from the native function as closely as it can. 这个额外的检查基本上是尽可能地从本机函数模拟这种健全性检查。


So why do we have to check the type of this ? 那么,为什么我们要检查的类型this

You don't technically have to , as this case would be an edge-case for most sane code, but in order to make the polyfill behave more-closely to the ES5 spec, it is nice. 在技术上不就得了 ,因为这种情况下将是一个边缘情况下最明智的代码,但为了使填充工具的行为更贴近于ES5规范,这是很好的。 Since ES5 browsers will never even run this code, there is also no performance hit for modern browser. 由于ES5浏览器永远不会运行此代码,因此现代浏览器也没有性能损失。


This behavior is defined in the ECMA-262 5.1 Edition specification and onward: 此行为在ECMA-262 5.1版规范及其后续版本中定义

  1. Let Target be the this value. Target 为此值。
  2. If IsCallable( Target ) is false , throw a TypeError exception. 如果IsCallable( Target )为false ,则抛出TypeError异常。

Not all callable objects inherit from (or are equal to) Function.prototype . 并非所有可调用对象都继承自(或等于) 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: 甚至从Function.prototype继承的对象也可以bind阴影:

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. 但是,您可能希望能够在这些可调用对象上调用Function.prototype.bind That's why we have things like Function.prototype.call , Function.prototype.apply or Reflect.apply . 这就是为什么我们有像Function.prototype.callFunction.prototype.applyReflect.apply这样的东西。 You can use those to call bind on any object, whether it's callable or not. 您可以使用它们在任何对象上调用bind ,无论它是否可调用。

The inverse is also possible. 反过来也是可能的。 You can have an object which inherits from Function.prototype and is not callable. 您可以拥有一个继承自Function.prototype且不可调用的对象。 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. 如果希望polyfill符合ES5,则必须检查对象是否可调用。 In ES5, checking whether typeof returns "function" does exactly that (but in ES3 it might not work for host objects). 在ES5中,检查typeof是否返回"function"就是这样(但在ES3中它可能对主机对象不起作用)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM