Array forEach pass “push” as argument

2019-02-27 11:57发布

问题:

Faced strange issue in JS. I receive error on this:

let a = []
let b = [1,2,3]
b.forEach(a.push)
TypeError: Array.prototype.push called on null or undefined
    at Array.forEach (native)
    at repl:1:3
    at REPLServer.defaultEval (repl.js:262:27)
    at bound (domain.js:287:14)
    at REPLServer.runBound [as eval] (domain.js:300:12)
    at REPLServer.<anonymous> (repl.js:431:12)
    at emitOne (events.js:82:20)
    at REPLServer.emit (events.js:169:7)
    at REPLServer.Interface._onLine (readline.js:211:10)
    at REPLServer.Interface._line (readline.js:550:8)

Sure, I've made a suggestion, that the context is lost. So, I try to accomplish that in this way:

b.forEach([].push.bind(a))

The result becomes unpredictable:

[ 1, 0, [ 1, 2, 3 ], 2, 1, [ 1, 2, 3 ], 3, 2, [ 1, 2, 3 ] ]

WHAT? =) Where is 0 from? Okay, maybe its "glitch"-index, but why not first than? :)

Just to make it clear, this works in a classical way, and that's not a question:

b.forEach(el => a.push(el) )

Can someone explain this strange behaviour?

回答1:

Basically as per the standard syntax of forEach, it is having 3 different parameters, current item, index and the array over which the forEach is called. So push function which was bound with a will be called every time with those parameters. That is the issue here.

iteration 1 : a.push(1,0,[1,2,3]) //since a was bound with push
iteration 2 : a.push(2,1,[1,2,3])
iteration 3 : a.push(3,2,[1,2,3])

Your code will be executed like above.



回答2:

Because .forEach() supplies to your callback 3 arguments.

callback is invoked with three arguments:

  1. the element value
  2. the element index
  3. the array being traversed

The .push() can accept any number of arguments. So, on each iteration, .push() adds those three arguments to your array.