JavaScript数组some方法调用bind绑定函数时行为不一致问题
问题现象
经bind绑定后的函数,在不同调用方式下返回结果存在差异,示例代码如下:
var str = 'sss'; var f = str.endsWith.bind(str); // 输出false console.log(['s', 'q', 'r'].some(f)) // 输出true console.log(['s', 'q', 'r'].some(value => f(value))) // 输出true console.log(f('s'))
核心疑问:为什么第一个some方法调用没有返回预期的true。
原因说明
遗漏的核心知识点有两个:
- 数组的遍历方法(
some/forEach/map/filter等)向传入的回调函数传递的参数共有3个:当前遍历到的元素、当前元素的索引、原数组本身,并非只有元素本身一个参数。 String.prototype.endsWith接收2个参数:第一个是要匹配的子串,第二个是可选的结束位置参数,作用是将原字符串截断到指定长度后再判断结尾,默认值为原字符串的总长度。
当直接把绑定后的f传给some时,遍历过程中实际调用等价于:
- 遍历第一个元素
s:执行f('s', 0, ['s','q','r'])→ 等价于str.endsWith('s', 0),即把sss截断为前0个字符(空字符串)判断是否以s结尾,返回false - 遍历第二个元素
q:执行f('q', 1, ['s','q','r'])→ 等价于str.endsWith('q', 1),即把sss截断为前1个字符(s)判断是否以q结尾,返回false - 遍历第三个元素
r:执行f('r', 2, ['s','q','r'])→ 等价于str.endsWith('r', 2),即把sss截断为前2个字符(ss)判断是否以r结尾,返回false
三次调用全为false,因此最终some返回false。
另外两种调用返回true的原因很简单:
- 箭头函数包装的写法,显式只向
f传递了元素本身一个参数,索引、原数组参数都被丢弃,endsWith使用默认的结束位置(字符串总长度3)判断,sss以s结尾,因此第一次遍历就返回true - 直接调用
f('s')时同样只传入了一个参数,匹配逻辑符合预期,返回true
快速验证
可以通过打印入参的方式确认传参情况:
var str = 'sss'; var f = function(...args) { console.log('f接收到的参数:', args); return str.endsWith(...args); } // 执行后可观察到每次调用f都收到了3个参数 console.log(['s', 'q', 'r'].some(f))
内容的提问来源于stack exchange,提问作者slevin
相关产品推荐
相关产品推荐

