功能的冗余类型检查?
Redundant type checking for function?
在 Array.prototype.forEach
js mdn 的 Polyfill 部分,您可以找到以下检查:
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
在这种特定情况下,为什么还要检查功能?在我的测试中,直接调用该函数会产生完全相同的行为
var callback;
callback();
// Uncaught TypeError: callback is not a function
var callback = "";
callback();
// Uncaught TypeError: callback is not a function
var callback = 2;
callback();
// Uncaught TypeError: callback is not a function
var callback = [];
callback();
// Uncaught TypeError: callback is not a function
var callback = {};
callback();
// Uncaught TypeError: callback is not a function
实际上这种字符串连接有点糟糕,因为我们可能会看到 "[object Object] is not a function"
:
function newCallback(val){
if (typeof val !== 'function') {
throw new TypeError(val+ ' is not a function');
}
}
newCallback({});
//Uncaught TypeError: [object Object] is not a function
In this specific case, why bother checking for function?
如果数组为空,则不会尝试调用该函数,但它 should still fail.
[].forEach('foo')
当元素访问具有 side-effects 时,non-empty 数组也有区别:
let foo = {
get [0]() {
alert(1);
}
};
Array.prototype.forEach.call(foo, …);
// alert shows up if the early type check is missing
forEach 的行为是这样定义的 15.4.4.18 Array.prototype.forEach:
- Let
O
be the result of calling ToObject
passing the this
value as the argument.
- Let
lenValue
be the result of calling the [[Get]]
internal method of O
with the argument "length"
.
- Let
len
be ToUint32(lenValue)
.
- If
IsCallable(callbackfn)
is false
, throw a TypeError
exception.
- If
thisArg
was supplied, let T
be thisArg
; else let T
be undefined
.
- Let
k
be 0
.
- Repeat, while
k
< len
[...]
并且因为polyfill是按照规范实现的,所以测试if callbackfn
是一个函数(4.)必须在迭代开始之前完成( 7.).因此,即使未调用 callbackfn
(在 len
为 0
的情况下),也会抛出错误。
我只是注意到他们没有像我那样明确地调用 callback
(callback()
) 而是他们调用 callback.call()
,这不再产生相同的行为并且在这种情况对于确保对象是函数类型是有意义的。
// Call the Call internal method of callback with T as
// the this value and argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
在 Array.prototype.forEach
js mdn 的 Polyfill 部分,您可以找到以下检查:
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
在这种特定情况下,为什么还要检查功能?在我的测试中,直接调用该函数会产生完全相同的行为
var callback;
callback();
// Uncaught TypeError: callback is not a function
var callback = "";
callback();
// Uncaught TypeError: callback is not a function
var callback = 2;
callback();
// Uncaught TypeError: callback is not a function
var callback = [];
callback();
// Uncaught TypeError: callback is not a function
var callback = {};
callback();
// Uncaught TypeError: callback is not a function
实际上这种字符串连接有点糟糕,因为我们可能会看到 "[object Object] is not a function"
:
function newCallback(val){
if (typeof val !== 'function') {
throw new TypeError(val+ ' is not a function');
}
}
newCallback({});
//Uncaught TypeError: [object Object] is not a function
In this specific case, why bother checking for function?
如果数组为空,则不会尝试调用该函数,但它 should still fail.
[].forEach('foo')
当元素访问具有 side-effects 时,non-empty 数组也有区别:
let foo = {
get [0]() {
alert(1);
}
};
Array.prototype.forEach.call(foo, …);
// alert shows up if the early type check is missing
forEach 的行为是这样定义的 15.4.4.18 Array.prototype.forEach:
- Let
O
be the result of callingToObject
passing thethis
value as the argument.- Let
lenValue
be the result of calling the[[Get]]
internal method ofO
with the argument"length"
.- Let
len
beToUint32(lenValue)
.- If
IsCallable(callbackfn)
isfalse
, throw aTypeError
exception.- If
thisArg
was supplied, letT
bethisArg
; else letT
beundefined
.- Let
k
be0
.- Repeat, while
k
<len
[...]
并且因为polyfill是按照规范实现的,所以测试if callbackfn
是一个函数(4.)必须在迭代开始之前完成( 7.).因此,即使未调用 callbackfn
(在 len
为 0
的情况下),也会抛出错误。
我只是注意到他们没有像我那样明确地调用 callback
(callback()
) 而是他们调用 callback.call()
,这不再产生相同的行为并且在这种情况对于确保对象是函数类型是有意义的。
// Call the Call internal method of callback with T as
// the this value and argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);