15 ms·
Object.observe withdrawn from TC39
- iamleppert 11y agoSad about this. I think we still need a high performance way to observe changes on objects without a lot of framework bloat.
- andrewmcwatters 11y agoGod forbid people use things like mutators and accessors or fire events.
- taylorbuley 11y agoJavaScript is all over eventing. But such a system requires cooperation or control between those firing and those subscribing to events. When the object we're talking about is e.g. an HTMLIFrameElement and it changes its own height it would be neat to be able to peek into object attribute changes.
- andrewmcwatters 11y agoNo, JavaScript is a language embedded in browsers. Web specifications detailing standard events are all over eventing, because browsers use event loops. On a related matter, Node does, too. JavaScript does not require an event loop. Any misunderstandings within this system are a misunderstanding regarding DOM events. HTMLIFrameElements don't change on their own. If they change based on the window resizing, you listen to the "resize" event, etc.
- bzbarsky 11y ago> JavaScript does not require an event loop. It actually does now that Promise got added to the language. For extra fun the interaction of the JavaScript event loop and the HTML/DOM event loop is not actually specified and getting it specified will be rather exciting: both sides want to "own" the event loop...
- _ZeD_ 11y agojust to add spice: there is also the CSS loop (with events like hovering and animations and stuff...) that is interesting to handle
- bzbarsky 11y agoHovering is handled via the HTML/DOM event loop, since it needs to be coordinated with mouseover events. Animations, though, do need to be worked into this somehow. And they need to be able to run on a completely independent event loop to some extent so you can do animations on the compositor thread, not the DOM thread.
- andrewmcwatters 11y agoI wonder how that works in practice outside of web environments, considering the spec doc doesn't mention it anywhere. I get the premise of having Promises in the language requiring an event loop, but without one, you'd be creating objects that never get resolved across frames (since they don't exist), which is still entirely possible.
- bzbarsky 11y agoThe spec doc sort of mentions it: http://www.ecma-international.org/ecma-262/6.0/#sec-jobs-and-job-queues http://www.ecma-international.org/ecma-262/6.0/#sec-jobs-and... and when you initially start up your environment you do http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-initialization http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascri... which ends with a NextJob call. So you have to go do a Job. There are various sorts of Jobs, but all of them end their processing steps with a NextJob call. I guess the only issue is that what happens if you have unresolved promises when your Job queues go empty is implementation-defined, because an implementation is allowed to terminate when there are no Jobs. But if it doesn't terminate, resolving the Promise will enqueue a PromiseReactionJob. And I guess not actually call NextJob; that part is up to the implementation.
- lyschoening 11y agoThere's still Proxy for that. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy https://developer.mozilla.org/en/docs/Web/JavaScript/Referen...
- toomim 11y agoIndeed, Proxy always seemed like the more general version of Object.observe. It not only "tells you when state changes", but lets you write code to say what that means. What's the state of Proxy? Are the people behind it still working on it? Are we going to be able to use it? Will it be fast?
- thomasfoster96 11y agoProxy has already been standardised (in ES6) so it should be coming into browsers soon. It's a little harder to polyfill than O.o though.
- AnkhMorporkian 11y agoAs far as I know Proxy is impossible to polyfill. There are some patches which make old browser versions of Proxy meet the spec, but I just don't think you can close the Proxy gap with pure javascript.
- pipeep 11y agoIt's possible if you also translate all of the code that uses the polyfilled object by converting every MemberExpression to a function call, but that's probably a nightmare for performance.
- bcherny 11y agowhat happens when i add a property to the object that i'm proxying after the Proxy is already instantiated? you wouldn't be able to detect the addition and add getters/setters for the property unless you use some sort of O.o or dirty checking on the underlying object. see https://github.com/bcherny/auditable https://github.com/bcherny/auditable for an implementation, sans O.o.
- PhrosTT 11y agoI know everybody loved this feature, but I was pretty scared of all the gross code junior devs might have made with this.
- ihsw 11y agoJunior devs? I could see this being yet another gross tool used by seasoned and junior devs alike, with the former trying to be clever with over-engineered solutions and the latter not knowing better.
- paulhodge 11y agoDon't worry, Proxy is still on the way, and that will still give us a tremendous ability to write terrible, unintelligible code.
- aikah 11y ago> and hope to remove support from V8 by the end of the year (the feature is used on 0.0169% of Chrome pageviews, according to chromestatus.com). I hope nobody uses that stuff in production ... even if there are polyfills, their performances are nowhere near the performances of the native implementation. > After much discussion with the parties involved Would be interesting to know the content of these discussion.
- noelwelsh 11y agoIn my opinion this is a good move. As the post notes, the JS world is moving away from the side-effect heavy code that motivates Object.observer. JS doesn't need any more legacy mistakes enshrined in the language spec, and without an overwhelming need for this it should not be adopted.
- Silhouette 11y agoAs the post notes, the JS world is moving away from the side-effect heavy code that motivates Object.observer. It may well be that Object.observer was the wrong level of granularity, and I agree that language specs should evolve cautiously. That said, I think it is far too early to make generalisations as broad your statement above. React-style development is still a tiny fraction of overall web development, and React itself isn't even at version 1.0 yet and IMHO still has significant fundamental architectural concerns that haven't been fully explored yet. It promotes some interesting ideas, and I'm glad someone with the profile of Facebook is challenging assumptions, but in turn reasonable people could challenge a lot of the ideas coming out of the React team and we're still far from understanding the long-term trade-offs of that style of building for the web.
- dccoolgai 11y agoI hope they keep it in V8, if only for debugging. There are some cases where this is the only practical way to see what is mucking with your object and when. If they take it out of the spec, it would be nice if they could add it as a method to console or something, at least.
- randomfool 11y agoIsn't it an async callback though? IMHO, it would be much more useful if it were synchronous.
- dccoolgai 11y agoIt is, but in Chrome devtools it shows you the source of the callback in the stack trace.
- stymaar 11y agoFor debugging purpose, that's exactly what Object.watch does (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/watch https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...) but this is only a SpideyMonkey feature.
- lemevi 11y agoConsider using a `Proxy` object. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- bcherny 11y agomaybe chrome will support this soon...
- AnkhMorporkian 11y agoProxies are brilliant. I used one to create an promise based RPC system that allows you to call any method you want. So before proxies, we used to do it as: await server.rpc.run("methodName", [argumentOne, argumentTwo]) Now, we just do: await server.rpc.methodName(one, two) The proxy traps that method call and returns a promise that runs that on the server. It's very slick and has made our code a lot more readable.
- filoeleven 11y agoWhat are the implications of this for Angular 2.0? Aren't they basically relying on this feature to make the framework efficient? Or was that just for improving Angular 1.x?
- pkozlowski_os 11y agoNeither Angular 2 nor 1 uses O.o for change detection. So there are no implications for ng, realy.
- cheapsteak 11y agoWhat does Angular 2 use for change detection?
- otodockal 11y agoThey have own solution called "ultrafast change detection" https://www.youtube.com/watch?v=jvKGQSFQf10 https://www.youtube.com/watch?v=jvKGQSFQf10
- Bahamut 11y agoAngular 2 is using observables via https://github.com/reactivex/rx.js https://github.com/reactivex/rx.js
- skeoh 11y agoYour link 404s. https://github.com/ReactiveX/RxJS https://github.com/ReactiveX/RxJS
- Bahamut 11y agoOops - sorry about that, typed that on a phone
- cheapsteak 11y agoTried googling for a source but came up empty. Could you provide one?
- bcherny 11y agoBummer. The latest web trend is immutability and event streams, but javascript data structures are almost all mutable by default, and O.o is a great way to take advantage of that fact. Instead of abstracting away data changes behind events, why not use data directly? Instead of fighting the language, why not (at times) embrace mutability?
- msvan 11y agoAlternatively, why not embrace immutability and add native immutable data structures to JS? I believe there is a TC39 proposal for this, in fact. Even if O.o had become mainstream, I would've stayed away from it. The immutability trend is not due to the impracticality of dealing with object observation, but due to inherent issues with mutable state.
- smasher164 11y agoHere's that proposal. https://github.com/sebmarkbage/ecmascript-immutable-data-structures https://github.com/sebmarkbage/ecmascript-immutable-data-str...
- bcherny 11y agoha! i actually commented on this guy a few months ago. javascript is designed in such a way that i think true, clojure-like immutable data structures are not possible. we'd either need to overload comparators (===, ==) so that they compare immutable data by value (rather than by reference, which is the case for their mutable counterparts), or implement java-style .equals methods for immutable objects (or as static methods on their constructors). neither seems to be a great fit for javascript. see my comment here https://github.com/sebmarkbage/ecmascript-immutable-data-structures/issues/4#issuecomment-99555565 https://github.com/sebmarkbage/ecmascript-immutable-data-str...
- keville 11y agoI think performance is the reason, but that's only speculation from a long-time JavaScript developer with plenty of in-the-trenches experience on resource-constrained platforms. The platforms that do not shy away from data and embrace mutability at all times -- I believe those are called databases, and when necessarily distributed for scale, that mutability is the enemy of consistency.
- michaelsbradley 11y agoAny implications for Google Polymer? I haven't kept up, but I remember from the time that I was working with it, Polymer depended on (i.e. built upon) either a native implementation of Object.observe or a polyfill that performs "dirty checking". The latter is not exactly a high performance underpinning for a library (though it works, sure).
- bsimpson 11y agoFrom the letter: > Polymer rewrote from the ground up for its 1.0 release, and in that rebuilding did not utilize O.o
- michaelsbradley 11y agoAh, thanks... I read the headline, glanced quickly at the link and typed up my polymer-related question as it came to mind. I should have actually read the letter. :-)
- pavlov 11y agoIn my experience, observing individual properties on model objects just isn't very useful in real world apps. Cocoa has long offered "key-value observing" (KVO) for this purpose, but other mechanisms like notifications tend to be more practical, usually because listeners need some context in order to do the best thing in response to a change, and an individual property change won't carry any of that context. Here's a practical example... Imagine an editor where an on-screen element is deleted. The controller might do a bunch of stuff such as: element.parent = nil scene.clearReferencesToElement(element) container.delete(element) self.selection = [] If there's a listener on "container", it will get notified even before the selection was cleared. That's probably not the intention. If we know that's going to happen, we could move the selection manipulation before the container access... But then we have fragile code that depends on implicit behavior in a model class. Always better to send an explicit event.
- tolmasky 11y agoI now subscribe to the React-style "wait, why are you listening to anything?" mindset. However, if you're going to go down the mutable path, I think KVO was particularly well designed. The main reason was that it made composition pretty sane and created clear places to handle changes. With KVO, you implement your KVO-compliant mutation methods, and all changes would then get funneled through there (most notable container ones). Compare the mess that is NSView (addSubview/insertSubview:positioned:relativeTo:/removeFromSuperview/etc) to the post-KVO NSTreeNode. NSTreeNode simply exposes .mutableChildNodes, which you treat as a normal array (addObject:/etc) and after adding a child, it then has parentNode set to the parent after. This was great for lots of reasons: 1. No need to re-create API, you just used NSMutableArray's existing API. So [someNode.mutableChildNodes removeObjectsWithPredicate:somePredicate] and all the parentNode relationships get handled for free. Compare this to pre-KVO methods where every time you wanted to take advantage of a neat NSMutableArray feature, you'd have to re-expose it yourself like removeSubviewsWithPredicate:, or wind up having to copy out the array, mutate, then re-assign with setSubviews: 2. Less room for error since all your cleanup code just happens in removeObjectFrom<Key>AtIndex:, one funnel. Again, I believe this to be a great local maxima for this style of programming, one that was never that fully explored since the move to more KVO-ness was eclipsed by the attention to iOS. I think most the problems are better solved through React's top-down approach.
- andrewmcwatters 11y agoObject.observe in itself was a declaration that the web community at large is not ready for serious software development yet. Any seasoned developer would see the ignorance in implementing such a feature.
- angersock 11y agoI used to work on a legacy Java codebase that made heavy (mis)use of the Observable pattern, and I must second your sentiment. Invariably a system acquires enough stuff going on that you get "observer storms" of feedback, or people find really weird couplings that are not immediately obvious because something several modules away is observing something it doesn't need to.
- acbabis 11y agoIn order to observe an Observable object, you need to have a reference to it. Adding an Observer to something that you shouldn't isn't possible without introducing it as a dependency. If someone does inject something so they can observe it, it's easier to spot the coupling. It sounds like the legacy code you got stuck maintaining put logic inside the observers, which isn't the Observer Pattern's fault. In my own experience, not using event patterns like the Observer Pattern is probably the biggest cause of difficult-to-maintain code.
- i38608 11y agoHow dare they use a feature that is not significantly different from using a setter for every property! These young people ought to know better.
- andrewmcwatters 11y agoI'd hate to be the one reviewing your code. I'm probably younger than you, too.
- nevir 11y agoI think the main thing that hamstrung Object.observe was that observations were asynchronous (scheduled as a microtask). It made data flow very difficult to follow for developers (particularly when driven by data binding systems).
- strictfp 11y agoThe original web 1.0 where each state had an url and was rendered sequentially from scratch was actually arguably much better than the stateful event-driven UI mess we have now. Moving from raw native ui frameworks very similar to todays js UI libs to HTML pages was a big paradigm shift, but was IMO better for most standard apps. I've been thinking for a long time that it would be a good idea to build a client-side library where each state has an URL. Essentially just take the classic backend view rendering technique and move it to the client. Could work out really well I think. Event-driven techniques can then be reserved for really interactive apps like games.
- mindcrime 11y agoClassic example... I login to the EMR system my GP's office uses, and click around a bit, looking at test results, notes, etc. Then, for whatever reason, I happen to reload the page or click the "back" button. Boom, I'm out of the application and have to login again from scratch. Grrrrr... SPA's and this fancy stuff have their place, but let's not pretend that it doesn't come with a cost.
- cglace 11y agoYou can have SPA's and the ability to reload and maintain application state.
- iwilliams 11y agoI could be wrong, but I think what you are asking for is covered in Ember's router.
- acbabis 11y agoI understand wanting to discourage directly mutating Objects, but I wish we knew what was going to replace O.o. IMO, we should have access to something like NodeJS' EventEmitter in the browser natively.
- gavargas08 11y agohttps://github.com/zenparsing/es-observable https://github.com/zenparsing/es-observable
- z3t4 11y agoWe still have Object.defineProperty (ES5) where you can have functions for get and set. I use this for database ORM for native Node.js object persistence.
- paulftw 11y agoSo they expected major frameworks to switch to an unfinished spec without a clear ETA for approval and that didn't work out? I think this is a major blow to web performance. We are bound to perform O(every object on page) computations on every event, instead of O(tiny bit that's actually changed). This is how having a device with gigs of RAM, close to ghz CPU we still measure FPS of a page with one table and 5 images
- JDDunn9 11y agoA sad day for Javascript. Why were only frameworks considered? Some of us still prefer vanilla JS. Also, more options are better than fewer. This is like saying, "Hammers have become quite popular lately, so we've cancelled plans to make a screwdriver."
- wereHamster 11y agoThis is unfortunate. I used O.o to implement type-safe lenses in my TypeScript project (https://github.com/wereHamster/avers https://github.com/wereHamster/avers). I always cringe when I see Immutable.js `c.setIn(['some','deeply','nested','field'], x)`, so much opportunity for typos, and no support for refactoring. For a while now I wanted to use proxies, but they are only supported in Firefox, and no timeline when they get to Chrome. I'll have to see what I can use as replacement.
- tjholowaychuk 11y agoThank god.
- jjeswin 11y agoBelieve that they might have withdrawn on performance backgrounds.