2017-06-12 31 views
1

我一直在呼叫方法玩弄在JavaScript中,我发现了一些有趣的东西:JavaScript中的错误例外。类型错误呼叫不是功能

我创建一个自定义地图功能,我做了这样的事情:

function map(collection, callback, context) { 
    if (!collection || !collection.hasOwnProperty('length') || typeof(callback) !== 'function') { 
     throw new TypeError(); 
    } 

    var newArray = []; 
    var isFunction = typeof(callback.call) === 'function'; // this I added after to prove my point. 
    console.log('is callback.call a function? ' + (isFunction ? 'yes it is!' : 'no, it is not a function')); 
    for (var i = 0, len = collection.length; i < len; i++) { 
     newArray[i] = callback.call(context, collection[i], i, collection); 
    } 

    return newArray; 
} 

在这一点上我执行我的map功能具有以下参数:

var arr = map(Array.apply(null, { length: 2 }), Number.call); 

我跳过了上下文参数值,所以它是undefined。这应该是很酷的。还有什么有点奇怪,因为callback我通过了call方法所以最后:我调用call方法call方法(这也很酷)。

但不知什么原因,浏览器给了我这个错误:

is callback.call a function? yes it is! 
Uncaught TypeError: callback.call is not a function 
    at map (eval at map (:10:9), <anonymous>:10:32) 
    at eval (eval at map (:10:9), <anonymous>:15:11) 
    at map (<anonymous>:10:9) 
    at <anonymous>:1:1 

我不知道这背后真正的理由。 callback.call肯定是一个函数。 有没有办法处理这种情况?我如何检查提供的参数是否会给我这样的错误?

这是当我提供上下文:

map(Array.apply(null, { length: 2 }), Number.call, Number) 
// is callback.call a function? yes it is! 
// [0, 1] 

CodePen(缺少控制台的错误,我建议使用浏览器来重现)

编辑: 只是为了澄清情况下不需要在所有:

map([1, 2], function(i) { 
    return i + 5; 
}); 
// is callback.call a function? yes it is! 
// [6, 7] 

编辑#2 我可以看到其他的问题是如何与我的关系。他们解释这背后的原因,还对火狐有相当不错的错误消息是:

TypeError: Function.prototype.call called on incompatible undefined 

所以我的最后一个问题是:

有没有一种方法来检测这种“不兼容”的?

+0

是的,你已经知道原因了:它缺少上下文。更好的错误消息应该是'Number.call中的Uncaught TypeError:上下文不是函数',但他们无法命名这些值,并且错误发生在'callback中。调用' – Bergi

+0

你的if语句说typeof(callback)!=='function'',你的isFunction变量等于'typeof(callback.call)==='function';'你的问题可能是你的if语句只是说回调,而不是callback.call? – Harry

+0

为什么不在if语句之外获得变量,然后在if语句中检查变量? – Harry

回答

1

您正在通过Number.call函数作为参数。所以在你的map函数callback里面变量现在已经是Number.call函数了。那么你不应该再使用callback.call了。只需使用callback即可解决。

这只是我的2美分的想法。希望能帮助到你!

编辑:因为callFunction.prototype的功能,所以它会出现在每个函数实例中。它需要this上下文成为一个函数。此刻,您将Number.call传递给您的新map,您已经失去了上下文,因为在新的map,this不再是函数。

+0

关键是'callback.call'是一个函数,即使认为似乎是不合适的。我的问题是,是否有可能发现它?为什么这样我得到这样的错误? –

+0

因为'call'是'Function.prototype'的函数,所以它会出现在每个函数实例中。 –

+0

请看我更新的答案。 –