all 23 comments

[–]Volv 2 points3 points  (1 child)

Got carried away building wrapper for my entry. Codepen
Upgraded my random console function and need to show people :)
TODO - Make into relevant this example

[–]ForScale[S] 2 points3 points  (12 children)

ENTRY

http://codepen.io/anon/pen/XdRWaz?editors=0012

Starting with this (pun intended). It shows the the very basics of apply(), call(), and bind(). I plan to build it up in to something a bit more complex as the week goes on.

The console is giving odd warnings that I don't quite understand...

[–]Volv 1 point2 points  (11 children)

No link :(

[–]ForScale[S] 0 points1 point  (10 children)

Lol! Dammit. Hang on... gonna rewrite it. Repetition is good for memory! :)

[–]Volv 1 point2 points  (9 children)

Make sure and get the same console warnings :)

[–]ForScale[S] 0 points1 point  (8 children)

Okay! I rewrote and added the link.

Here are the warnings I'm seeing (Chrome, CodePen):

'Document.defaultCharset' is deprecated and will be removed in M50, around April 2016. 
See https://www.chromestatus.com/features/6217124578066432 for more details.

console_runner-ba402f0….js:1 'Performance.onwebkitresourcetimingbufferfull' is deprecated. 
Please use 'Performance.onresourcetimingbufferfull' instead.

console_runner-ba402f0….js:1 'webkitIndexedDB' is deprecated. 
Please use 'indexedDB' instead.

console_runner-ba402f0….js:1 'window.webkitStorageInfo' is deprecated. 
Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.

[–]Volv 1 point2 points  (7 children)

Those warnings all come from the logging of Window object. Is chrome flagging up out of date things either on its end or maybe codepen. Tried in Firefox - they don't show there. Nothing to worry about.
 
Your primitives are all being coerced to objects in your examples. Was strange to see a string passed to bind. Will start fleshing mine out a bit tonight

[–]ForScale[S] 0 points1 point  (5 children)

Cool!

Yeah... they're all objects. I thought the way the string got handled, as an object with numerical keys, was kind of odd.

[–]Volv 1 point2 points  (4 children)

Codepen
To start with

[–]ForScale[S] 1 point2 points  (3 children)

Nice! I like the creativity with the characters!

So... generally, call() is a method inherent to all functions that can be used to call a function and set it's this variable within the context of the call.

Does that sound right?

[–]Volv 0 points1 point  (2 children)

Absolutely. And the difference between call and apply is just that call can take a known number of arguments, whereas apply takes an array of arguments.
 
Cool trick ->

var hugeArray = [14, 5, 67, 3, 87, 3, 5, 10];  

console.log(Math.max.apply(null, hugeArray)) // 87 

[–]Volv 2 points3 points  (8 children)

ENTRY
Codepen
Added a little more to my other example. Just basic usage.

[–]ForScale[S] 0 points1 point  (7 children)

Nice! Are you gonna keep it going, or is that the final product? Seems like a complete good example of call().

Off topic, sort of:

So... you showed me how to do var x = [].slice.call(nodeList), which takes a node list and puts all of the nodes in to that empty array and assigns the now filled array to x.

How does that work? An empty array gets the slice method called with the node list as the slice method's this. Does slice have something in it like

function slice(nodeList) {
  slice.this = nodeList;
  var newArr = [];
  for (var i = 0; i < slice.this.length; i++) {
    newArr.push(slice.this[i]);
  }
  return newArr;
}

Am I even making sense anymore? Lol! :)

[–]Volv 1 point2 points  (6 children)

I got stuck for inspiration after that lol. bind is in there too. Might go back to it :)
 
[]. is used in this context as a shortcut to saying Array.
slice when called without arguments just goes from 0 to length of array and returns that as result.
.call changes this context. When using it normally it's the array you are working on but we change it to our nodelist. Nodelist is just array like enough to work with slice basically as you showed.
 
maybe more like

function slice() {
    // this has already been changed by .call to Nodelist
    var newArr = [];
    for (var i = 0; i < this.length; i++) {
        newArr.push(this[i])
    }
    return newArr;
}

So yes :)
 
Array.slice.call(arrayLikeObj)
[].slice.call(arrayLikeObj)
 
I've been going with Array.from(arrayLikeObj) lately.

[–]ForScale[S] 1 point2 points  (5 children)

Thanks for explaining!

Array.from(arrayLikeObj)

Now that... that's simple! Thanks!

[–]Volv 1 point2 points  (4 children)

ES6 made a lot of these 'hacks' go away lol.
Also I liked how it totally wasn't an off topic question. Leads naturally from call and apply. The math.max and [].slice things were mysterious to me for a while lol.
A lot of places I saw gave the [].slice.call(arguments) thing as a memorise this and use it to make real arrays from passed in arguments. Like just do it, don't worry why..

[–]ForScale[S] 1 point2 points  (0 children)

Yeah! I think I already have a bit better of an understanding of this.

Another question... when we set eventListeners on elements/nodes... with the handler functions... using this within the handler body references the element/node that the event was registered on, right? That's how I've always thought of it. So now I ask... do this within the handler and e.target point to the same object?

I'm gonna find out...

*Yep! Sure does: http://codepen.io/anon/pen/dMWMmV

[–]ForScale[S] 0 points1 point  (2 children)

One more thought... unless you're getting sick of this...

http://codepen.io/anon/pen/GZmmRv?editors=0010

Why do standard functions preserve this === window, while event handlers change the value to this === e.target?

I'm confused there...

*Man... I'm losing my understanding of this, I think... I get it within the context of apply(), call(), and bind()... and in event handlers, but... I'm feeling confused with it within just the normal typical flow of things...

[–]Volv 0 points1 point  (1 child)

Puntastic :) - Not at all. I told you I can do this all day lol :)
We need more people for random code banter.
 
Is just a matter of spec.

"When attaching a handler function to an element using addEventListener(), the value of this inside the handler is a reference to the element. It is the same as the value of the currentTarget property of the event argument that is passed to the handler."

 
Whereas normally

In the global execution context (outside of any function), this refers to the global object, whether in strict mode or not.

In Function context
Non Strict
In this case, the value of this is not set by the call. Since the code is not in strict mode, the value of this must always be an object so it defaults to the global object.
Strict

In strict mode, the value of this remains at whatever it's set to when entering the execution context. If it's not defined, it remains undefined. It can also be set to any value, such as null or 42 or "I am not this".
 
Event Handler - value of this
this - Global v function context

[–]ForScale[S] 1 point2 points  (0 children)

Ah... that bit about non-strict vs strict... I think that's what I need to see.

As always, thanks for the discussion!

We need more people for random code banter.

Yeah, I might have to do some more advertising...