为何Array.prototype.includes.bind表现不符合预期?
Great question! Let's break down exactly why these two snippets behave differently—it all comes down to how Array.prototype.some passes arguments to its callback, and the different parameter signatures of native includes vs. Underscore.js's includes.
Why the Native includes.bind Version Returns false
First, remember how Array.prototype.some works: it runs your callback function on every element in the array, passing three arguments to the callback each time:
- The current element being processed
- The index of that element
- The original array that
somewas called on
When you create Array.prototype.includes.bind([3,4,5]), you're locking in the this value of includes to be the array [3,4,5]. But here's the critical detail: native Array.prototype.includes accepts two parameters:
searchElement: the value you want to findfromIndex: the position in the array to start searching from (optional)
When some calls this bound includes function, it's passing the current element as the first argument (which becomes searchElement), and the index as the second argument (which becomes fromIndex). Let's walk through each iteration step by step:
- First element:
[3,4,5].includes(1, 0)→ checks for1starting at index 0 →false - Second element:
[3,4,5].includes(2, 1)→ checks for2starting at index 1 →false - Third element:
[3,4,5].includes(3, 2)→ starts searching at index 2 (where the value is5), so it never finds3→false
Since none of the callback calls return true, some ultimately returns false.
Why the Underscore.js Version Returns true
Underscore.js's includes method (on its prototype) has a different signature than the native version. Underscore's methods are built to work with their wrapped collections, so when you call _.prototype.includes on a wrapped array, it expects only the target value as its first argument (the collection itself is already bound as this).
When you do _.prototype.includes.bind(_([3,4,5])), you're binding the this value to the Underscore-wrapped [3,4,5] collection. Now, when some calls this bound function, it passes the current element as the first argument—and this becomes the target value Underscore's includes looks for. Let's walk through this:
- First element:
_.includes(_([3,4,5]), 1)→false - Second element:
_.includes(_([3,4,5]), 2)→false - Third element:
_.includes(_([3,4,5]), 3)→true
As soon as the third call returns true, some stops iterating and returns true.
Key Takeaway
The core difference is the parameter order and purpose:
- Native
Array.prototype.includesuses(searchElement, fromIndex) - Underscore's
_.includes(when called on a wrapped collection) uses(targetValue)
The extra arguments passed by Array.prototype.some get interpreted completely differently by each version of includes, leading to the opposite results.
内容的提问来源于stack exchange,提问作者Marnes

