8

Trying to refactor a simple function:

// arr - array of objects with functions
function eventNotify(arr, event) {
    for (var i = 0; i < arr.length; i++) {
        var a = arr[i];
        if (typeof a[event] === 'function') {
            a[event]();
        }
    }
}

into this one:

function eventNotify(arr, event) {
    for (var i = 0; i < arr.length; i++) {
        var a = arr[i][event];
        if (typeof a === 'function') {
            a();
        }
    }
}

I'm stuck trying to comprehend how such change manages to break all my tests.

How is it possible that the second implementation is functionally different from the first one?

I even tried to split the use of indexes, thinking that maybe it is treated as a 3D array:

var a = arr[i];
a = a[event];

But no, this makes no difference.

Please somebody point out what on earth am I changing in the logic of the algorithm there! I'm wracking my brain over this one now.


I'm testing it under Node.js 10.9

3
  • 7
    You're breaking the object relationship and therefore this won't be set when the function is called. Commented Aug 26, 2018 at 12:53
  • @Pointy So this on explicit array addressing works, as opposed to just a variable. I knew the secret was somewhere in the intensity of my head-banging on the table... But this one is quite a revelation. If you want to make it into an answer, I will accept it ;) Commented Aug 26, 2018 at 13:00
  • In the first example the function context (this value) is arr[i]. In the second, its the global object. Commented Aug 26, 2018 at 13:10

1 Answer 1

1

Thanks @Pointy

My mistake was in not being able to see that syntax a[event]() obscures the fact that it passes in this context set to object a, while simple a() does not, hence the result discrepancy.

Sign up to request clarification or add additional context in comments.

3 Comments

If you did want to do just -> a(), you could use bind. var a = arr[i][event].bind(arr[i])
@Keith I did this as part of some performance optimization, by replacing some forEach loops that work awfully slower than for inside old browsers, like IE9/10. And your solution would make it even slower than that, as you are calling a function that creates and returns another function that swaps calling context.
Using bind can actually increase performance, it of course depends how you use it. Using bind inside a loop would not be ideal though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.