在我的特殊情况下:

callback instanceof Function

or

typeof callback == "function"

这有关系吗,有什么区别?

额外的资源:

花园typeof vs instanceof


当前回答

这只是对这里所有其他解释的补充知识——我不建议在所有地方都使用.constructor。

TL;DR:在typeof不是一个选项的情况下,并且当你知道你不关心原型链的时候,Object.prototype.constructor可以是一个可行的甚至比instanceof更好的选择:

x instanceof Y
x.constructor === Y

它从1.1开始就在标准中了,所以不用担心向后兼容性。

Muhammad Umer也在这里的一个评论中简要地提到了这一点。它适用于所有有原型的东西——所以所有不是null或未定义的东西:

// (null).constructor;      // TypeError: null has no properties
// (undefined).constructor; // TypeError: undefined has no properties

(1).constructor;                 // function Number
''.constructor;                  // function String
([]).constructor;                // function Array
(new Uint8Array(0)).constructor; // function Uint8Array
false.constructor;               // function Boolean()
true.constructor;                // function Boolean()

(Symbol('foo')).constructor;     // function Symbol()
// Symbols work, just remember that this is not an actual constructor:
// new Symbol('foo'); //TypeError: Symbol is not a constructor

Array.prototype === window.frames.Array;               // false
Array.constructor === window.frames.Array.constructor; // true

此外,根据您的用例,它可能比instanceof快得多(原因可能是它不需要检查整个原型链)。在我的情况下,我需要一个快速的方法来检查一个值是否是一个类型数组:

function isTypedArrayConstructor(obj) {
  switch (obj && obj.constructor){
    case Uint8Array:
    case Float32Array:
    case Uint16Array:
    case Uint32Array:
    case Int32Array:
    case Float64Array:
    case Int8Array:
    case Uint8ClampedArray:
    case Int16Array:
      return true;
    default:
      return false;
  }
}

function isTypedArrayInstanceOf(obj) {
  return obj instanceof Uint8Array ||
    obj instanceof Float32Array ||
    obj instanceof Uint16Array ||
    obj instanceof Uint32Array ||
    obj instanceof Int32Array ||
    obj instanceof Float64Array ||
    obj instanceof Int8Array ||
    obj instanceof Uint8ClampedArray ||
    obj instanceof Int16Array;
}

https://run.perf.zone/view/isTypedArray-constructor-vs-instanceof-1519140393812

结果是:

Chrome 64.0.3282.167(64位,Windows)

Firefox 59.0b10(64位,Windows)

出于好奇,我针对typeof做了一个快速的玩具基准测试;令人惊讶的是,它的表现并没有差到哪里去,而且在Chrome中似乎还要快一点:

let s = 0,
    n = 0;

function typeofSwitch(t) {
    switch (typeof t) {
        case "string":
            return ++s;
        case "number":
            return ++n;
        default:
            return 0;
    }
}

// note: no test for null or undefined here
function constructorSwitch(t) {
    switch (t.constructor) {
        case String:
            return ++s;
        case Number:
            return ++n;
        default:
            return 0;
    }
}

let vals = [];
for (let i = 0; i < 1000000; i++) {
    vals.push(Math.random() <= 0.5 ? 0 : 'A');
}

https://run.perf.zone/view/typeof-vs-constructor-string-or-number-1519142623570

注意:函数列表的顺序在图像之间切换!

Chrome 64.0.3282.167(64位,Windows)

Firefox 59.0b10(64位,Windows)

注意:函数列表的顺序在图像之间切换!

其他回答

当然这很重要........!

让我们用例子来解释一下。在我们的例子中,我们将以两种不同的方式声明函数。

我们将同时使用函数声明和函数构造函数。我们将了解typeof和instanceof在这两种不同场景中的行为。

使用函数声明创建函数:

function MyFunc(){  }

typeof Myfunc == 'function' // true

MyFunc instanceof Function // false

对于这种不同的结果,可能的解释是,因为我们做了一个函数声明,typeof可以理解它是一个函数。因为typeof检查typeof的表达式是否被操作,在我们的例子中,MyFunc是否实现了Call Method。如果它实现了Call方法,它就是一个函数。为了澄清,请检查ecmascript的typeof规范。

使用函数构造函数创建函数:

var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used 

typeof MyFunc2 == 'function' // true

MyFunc2 instanceof Function // true

这里typeof断言MyFunc2是一个函数,也是一个instanceof操作符。我们已经知道typeof检查MyFunc2是否实现了Call方法。由于MyFunc2是一个函数,它实现了调用方法,这就是typeof如何知道它是一个函数。另一方面,我们使用函数构造函数来创建MyFunc2,它成为函数构造函数的一个实例。这就是为什么instanceof也解析为true。

用什么更安全?

我们可以看到,在这两种情况下,typeof操作符都可以成功地断言我们在处理一个函数,它比instanceof更安全。instanceof在函数声明的情况下将失败,因为函数声明不是function构造函数的实例。

最佳实践:

正如Gary Rafferty所建议的,最好的方法应该同时使用typeof和instanceof。

  function isFunction(functionItem) {

        return typeof(functionItem) == 'function' || functionItem instanceof Function;

  }

  isFunction(MyFunc) // invoke it by passing our test function as parameter

尽管instanceof可能比typeof快一点,但我更喜欢第二个,因为它可能有这样的魔力:

function Class() {};
Class.prototype = Function;

var funcWannaBe = new Class;

console.log(funcWannaBe instanceof Function); //true
console.log(typeof funcWannaBe === "function"); //false
funcWannaBe(); //Uncaught TypeError: funcWannaBe is not a function

这只是对这里所有其他解释的补充知识——我不建议在所有地方都使用.constructor。

TL;DR:在typeof不是一个选项的情况下,并且当你知道你不关心原型链的时候,Object.prototype.constructor可以是一个可行的甚至比instanceof更好的选择:

x instanceof Y
x.constructor === Y

它从1.1开始就在标准中了,所以不用担心向后兼容性。

Muhammad Umer也在这里的一个评论中简要地提到了这一点。它适用于所有有原型的东西——所以所有不是null或未定义的东西:

// (null).constructor;      // TypeError: null has no properties
// (undefined).constructor; // TypeError: undefined has no properties

(1).constructor;                 // function Number
''.constructor;                  // function String
([]).constructor;                // function Array
(new Uint8Array(0)).constructor; // function Uint8Array
false.constructor;               // function Boolean()
true.constructor;                // function Boolean()

(Symbol('foo')).constructor;     // function Symbol()
// Symbols work, just remember that this is not an actual constructor:
// new Symbol('foo'); //TypeError: Symbol is not a constructor

Array.prototype === window.frames.Array;               // false
Array.constructor === window.frames.Array.constructor; // true

此外,根据您的用例,它可能比instanceof快得多(原因可能是它不需要检查整个原型链)。在我的情况下,我需要一个快速的方法来检查一个值是否是一个类型数组:

function isTypedArrayConstructor(obj) {
  switch (obj && obj.constructor){
    case Uint8Array:
    case Float32Array:
    case Uint16Array:
    case Uint32Array:
    case Int32Array:
    case Float64Array:
    case Int8Array:
    case Uint8ClampedArray:
    case Int16Array:
      return true;
    default:
      return false;
  }
}

function isTypedArrayInstanceOf(obj) {
  return obj instanceof Uint8Array ||
    obj instanceof Float32Array ||
    obj instanceof Uint16Array ||
    obj instanceof Uint32Array ||
    obj instanceof Int32Array ||
    obj instanceof Float64Array ||
    obj instanceof Int8Array ||
    obj instanceof Uint8ClampedArray ||
    obj instanceof Int16Array;
}

https://run.perf.zone/view/isTypedArray-constructor-vs-instanceof-1519140393812

结果是:

Chrome 64.0.3282.167(64位,Windows)

Firefox 59.0b10(64位,Windows)

出于好奇,我针对typeof做了一个快速的玩具基准测试;令人惊讶的是,它的表现并没有差到哪里去,而且在Chrome中似乎还要快一点:

let s = 0,
    n = 0;

function typeofSwitch(t) {
    switch (typeof t) {
        case "string":
            return ++s;
        case "number":
            return ++n;
        default:
            return 0;
    }
}

// note: no test for null or undefined here
function constructorSwitch(t) {
    switch (t.constructor) {
        case String:
            return ++s;
        case Number:
            return ++n;
        default:
            return 0;
    }
}

let vals = [];
for (let i = 0; i < 1000000; i++) {
    vals.push(Math.random() <= 0.5 ? 0 : 'A');
}

https://run.perf.zone/view/typeof-vs-constructor-string-or-number-1519142623570

注意:函数列表的顺序在图像之间切换!

Chrome 64.0.3282.167(64位,Windows)

Firefox 59.0b10(64位,Windows)

注意:函数列表的顺序在图像之间切换!

其他重要的实际差异:

// Boolean

var str3 = true ;

alert(str3);

alert(str3 instanceof Boolean);  // false: expect true  

alert(typeof str3 == "boolean" ); // true

// Number

var str4 = 100 ;

alert(str4);

alert(str4 instanceof Number);  // false: expect true   

alert(typeof str4 == "number" ); // true

var newObj = new Object;//对象实例 var newProp = "I'm xgqfrms!"/ /定义属性 var newFunc = function(name){//定义函数 Var hello ="hello, "+ name +"!"; 返回你好; } //添加属性newObj.info = newProp newObj。//添加函数 console.log(newObj.info) //我是xgqfrms! console.log(newObj.func("ET")) //你好,ET! console.log(newObj instanceof Object); / /正确的 console.log (typeof (newObj)); / /“对象”