5 ms·
Very nice to see it starts off with a (correct) discussion of JS types! JS devs mostly don't know the actual types in JS, which is pretty crazy if you think abo
by serve_yay 11y ago
Very nice to see it starts off with a (correct) discussion of JS types! JS devs mostly don't know the actual types in JS, which is pretty crazy if you think about it.
- sergiotapia 11y agoI think 99% of the problems people have with Javascript are not actually types, but `this`. It's the most confusing part about Javascript. This context, var foo scope, what? Why is this value not updating? undefined? What???
- csandreasen 11y agoI actually found the Javascript 'this' keyword more understandable after working with Python. >>> class foo(): ... def test(this, x): ... print this, x ... >>> x = foo() >>> x <__main__.foo instance at 0xb71928ac> >>> x.test(1) <__main__.foo instance at 0xb71928ac> 1 >>> y = foo.test >>> y(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method test() must be called with foo instance as first argument (got int instance instead) >>> y(x,1) <__main__.foo instance at 0xb71928ac> 1 In Python, the reference to the current object is an explicitly declared parameter in the method definition, but the parameter is passed implicitly - the value of "this" is whatever is comes before the period when the method is called. If you call it in any other manner, it throws an unbound method error. Javascript is the same way, but instead of throwing an error it will instead pass 'window' implicitly. The equivalent code in Javascript: function foo() { } foo.prototype.test = function(x) { console.log(this, x); } var x = new foo(); x.test(1); // prints VM1061:4 foo {test: function} 1 var y = x.test; y(1); // prints VM1061:4 Window {top: Window, window: Window, …} 1
- reipahb 11y agoActually, what you get when referencing x.test in Python is a bound method: >>> foo.test <unbound method foo.test> >>> x.test <bound method foo.test of <__main__.foo instance at 0xf74d68ac>> >>> z = x.test >>> z(123) <__main__.foo instance at 0xf74d68ac> 123 I really like this behavior in Python. Unfortunately, JavaScript does not behave the same way, as you see in the last couple of lines in your example. You can however get the same result by manually binding the method to the object: z = x.test.bind(x) // z is: function () { [native code] } z(123) // foo {test: function} 123
- pluma 11y agoI came (back) to JS after doing a lot of Python and I think that may have helped understanding `this` in JS. Note that the behaviour of `this` defaulting to `window` (or `global`) is only the legacy behaviour. You should be using strict mode (there's really no justification not to -- except for extremely rare edge cases, e.g. having to delete global variables without having a reliable reference to the global object other than `this`). In strict mode, `this` would be undefined. As expected, if you consider `x.y()` syntactic sugar for `x.y.call(x)` (and therefore `z()` syntactic sugar for `z.call(undefined)`). Under the hood, invoking a function translates to a call of the functions `[[Call]]` method, which takes an explicit `this` just like `Function.prototype.call` does.
- tracker1 11y agoI find that testing works better when I define my functions separately from binding in objects. var foo = { doSomething:(...argv)=doSomethingMethod(foo, argv) }; return foo; In this way, the execution is always predictable, as I avoid the use of this altogether... It's my one niggle with koa, that it uses this (execution context) as the request/response context. I tend to it in practice. It's similar to what Crockford now presents as a preferred approach in dealing with having context for functions... I just like discrete functions that can be tested independently of their execution context... by passing the context as a parameter, this becomes explicit... with binding, the process becomes transparent.
- chris_wot 11y agoEspecially when you need to do something like: var that = this;
- bryanlarsen 11y agoThat's not generally necessary in ES6 when you use "=>" to define functions. Javascript is getting better...
- chris_wot 11y agoIt's really a minor criticism and I know ES6 resolves the issue :-)
- chris_wot 11y agoThrough bind of course, for the silly person who downvote me. Helps to have strict mode on. Happy to have educated you!
- neurosnap 11y agoWhat happens when you nest anonymous functions? Would you have to use the arrow operator at every level?
- sergiotapia 11y agoLooking at you Ember. Ugh! var controller = this; Every time!
- serve_yay 11y agoI agree, `this` is a disaster. But, I just can't hardly think of another language where the people working in it mostly don't know the types. (Well, OK, PHP devs probably mostly don't) And I don't just mean run-of-the-mill blub programmers who dabble in jQuery, I mean some of the best devs I've ever seen in any language. I had a self-proclaimed JS expert tell me that JS has integers and floats as distinct types. Even the people I work with every day who are fantastic did not know that function and array are not types. Of course, things like `typeof` don't help the situation, so I don't put the blame squarely on programmers' shoulders. And obviously you can get a lot done without knowing that, technically, functions are just objects that can be called. But it still strikes me as kinda crazy.
- barrkel 11y ago"technically, functions are just objects that can be called" How can you create an object which can be called like a function, but will respond to 'typeof' with 'object' rather than 'function'? What happens when you try to call an object - what's the error? Try it, in a few of your favourite javascript interpreters: ({})() It seems clear to me that functions are more than "just" objects in JS. You can't start out with a random {} and turn it into a function. JS functions are a subtype of JS objects, but they are a distinct type. You can't substitute an object where a function is expected - you get a type error - but you can substitute a function where an object is expected.
- serve_yay 11y ago> How can you create an object which can be called like a function, but will respond to 'typeof' with 'object' rather than 'function'? You can't, by definition. Here is the relevant section of the ECMAScript 5 spec: http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.3 http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.3 Basically, an object which implements call will always cause `typeof` to return "function". But the broader point is that `typeof` will lie to you and you shouldn't trust it for, you know, determining the types of values. (For example, the type of null is null, but `typeof null` returns "object".) As I noted above, this behavior of `typeof` is part of what causes the confusion around types in JS devs. > You can't substitute an object where a function is expected - you get a type error - but you can substitute a function where an object is expected. This is true, but not inconsistent with the notion that functions are objects which can be called. I encourage you to read the spec I linked above, or a draft of ES6.
- buckbova 11y agohttp://bjorn.tipling.com/all-this http://bjorn.tipling.com/all-this Good stuff here.
- yulaow 11y agoand 99% of those 99% problems can easily be solved with the correct use of .bind() or .apply().
- lewisl9029 11y agoUsing jspm, SystemJS and Babel for my latest project, and simply using let universally over var and arrow functions over anonymous functions has made this aspect of JavaScript behave like any sane language would. I simply don't ever need to think about it anymore.