5 ms·
I think the point was to simplify the JS Prototype syntax to be more "normal-looking" and less confusing to devs, not some rich OOP model compared to true OOP l
by gedy 8y ago
I think the point was to simplify the JS Prototype syntax to be more "normal-looking" and less confusing to devs, not some rich OOP model compared to true OOP languages.
- ChrisSD 8y agoJavascript is a true OOP language. I'm all in favour of simplifying some of the syntax but why call it a "class"? That's only going to further confuse matters. I already have a hard enough time trying to teach Javascript's OOP model without adding to the confusion.
- kowdermeister 8y agoWhy not? It's totally reasonable if you learn a language to get familiar with the concepts in it. Every language is different here and there and the 'class' describes well what it does: wrap things together that belong together.
- krapp 8y ago>and the 'class' describes well what it does: wrap things together that belong together. So does "Object". All "Class" does, here is paper over some of the complexity of making JS objects. If anything, JS classes hide necessary concepts about the language from the developer. At least with the old, ugly way of doing things, you were forced to confront prototypes and scope and how 'this' worked.
- dmitriid 8y ago> I think the point was to simplify the JS Prototype syntax to be more "normal-looking" and less confusing to devs So they bolted on an incompatible thing that hides prototypes and is confusing to devs: class C { y = 10; // this fine. "methods" defined as class properties // have access to proper `this` due to how class properties work // and scoping rules x = () => if(this.y > 10) this.y = 10; constructor() { // if you don't bind `this`, `method()` will not have access // to `this` this.method = this.method.bind(this) } method() { // will refer to a wrong `y` if `this` isn't bound // in the constructor this.y++; } }
- gedy 8y agoSure, but this is being addressed in: https://github.com/tc39/proposal-class-fields https://github.com/tc39/proposal-class-fields And available now as: https://babeljs.io/docs/en/babel-plugin-proposal-class-properties https://babeljs.io/docs/en/babel-plugin-proposal-class-prope...
- dmitriid 8y agoNo, it's not addressed. And you can see me using class fields already in `x = () => ...` <- this is a class field (I called it class property, sorry). The fact that arrow functions declared as class fields get access to the proper `this` in the class instance is just a happy(?) coincidence with its own downsides. For example, class fields can't be inherited in the child class. So this adds a yet another layer of confusion for devs. And as you see in the example at the link you provided, you still need to `.bind(this)` the actual methods.
- oklahoma 8y agoYou don't have to bind 'method' in the constructor to access 'y'. Just put 'this.y = 10;' in the constructor. Your example isn't legal JavaScript.
- dmitriid 8y agoIt's perfectly legal Javascript. Why would I put this.y = 10 in the cinstructor? Do you even understand what this code does? const instance = new C(); for(let i = 0; i < 20; i++) { instance.method(); } instance.x() If you don't bind `this` to `method` in the constructor, when you call `instance.method()`, `this` will be whatever (window, IIRC). Don't believe me? Try a more complex example like React's event handling with `this.setState()`: https://reactjs.org/docs/handling-events.html https://reactjs.org/docs/handling-events.html
- chrismorgan 8y agoThe `y = 10;` is a class field, which is part of a Stage 3 proposal, https://github.com/tc39/proposal-class-fields https://github.com/tc39/proposal-class-fields. It’s not yet finalised, though it’s getting there. No current browser supports it, and those that write their code thus depend on Babel or similar projects to transform the code into a property definition in the constructor. Chrome 72, the next release, introduces support for it. Decide for yourself whether all that counts as “perfectly legal JavaScript” or not! Now onto bound methods: you are wrong in your code example; `instance.method()` does not require `method` to be a bound method; an unbound function is just fine. The code is equivalent to `instance.method.call(instance)`, which (for an unbound function) calls it with `instance` as its context. The problem is when, at call time, you don’t access the function as a property on another object, like this: const fn = instance.method; fn(); Or `(1, instance.method)()`. Then you need to worry about what the context will be (in strict mode, it’ll be `undefined`, and so any property access on it will immediately blow up, which is good). Bound methods are created by Function.prototype.bind, or by arrow functions. In what I will choose to call “normal code”, it’s somewhere between very rare and not particularly common to need to bind a function manually. Understand this: React is not normal code. React was designed in a distinctly unusual way (they invented an rather substantial language extension to achieve it!), and although that language and design has turned out quite well in most ways, it also has some exceptionally nasty weaknesses and rather annoying ergonomic troubles; and the need to bind functions is one of them. This is not JavaScript’s fault, but is because React has gone for a VDOM approach that (I think?) requires object identity in such cases, for reasons of efficiency. In search of one form of ergonomics, they damaged another form that others don’t have to worry about very often at all. Such is life, and the nature of tradeoffs. Most of the trouble with needing bound functions happens with event handling. (Certainly not all, but most, in my experience.) In non-React, non-VDOM-based code, you might be doing something like this: const foo = document.createElement('foo'); foo.addEventListener('bar', event => { … }); … and that’d be perfectly fine there. And a whole lot more efficient at runtime than React, I might add. * If you needed `this`, then the arrow function got it for you automatically. Sometimes you would want a separate function to designate the event handler, and so you may want to call bind(), but it’s also just as likely that you’ll want to keep Event out of that method, and just do `foo.addEventListener('bar', event => this.handleBar(event.detail))`. Maybe, maybe not. From your earlier example: be careful with your `x = () => …` instead of `x() { … }`, because that instantiates a new function for every instance of the object, which is very inefficient for memory consumption and performance. Binding a method from the prototype is much more efficient (though still to be avoided where unnecessary). The most interesting approach to resolving this binding problem that React causes lies in the decorators proposal (currently at stage 2). https://github.com/tc39/proposal-decorators/blob/master/bound-decorator-rationale.md https://github.com/tc39/proposal-decorators/blob/master/boun... is all about a @bound decorator. * Just be careful with adding event listeners, and remember to use bubbling.