Cocoa Touch (iOS) got rid of bindings altogether and you manage updates manually (although I use a bindings library to emulate the old OSX bindings support in one of my apps).
Not sure on macOS, bindings may still exist there.
That's exactly my point. The concept of bindings (in the sense of two-way-bindings) hasn't proved to be successful - neither today nor in the past, neither on desktop or in the web.
As a more general throught:
When comparing concepts or patterns, there are often discussions about which one is better, comparing different but almost equally good options. Choosing the "best" one is hard. So the list of advisable patterns is constantly evolving and changing.
However, some concepts clearly didn't pay off over decades across a huge variety of settings. These anti-patterns are quite stable, and more or less just growing, not changing. It may make sense to collect these ones.
The "good" concepts may be subject to fashion and evolution, but the "bad" ones are stable and hence worth collecting.
Two-way bindings are great for prototypes because you no longer need to think about how your state gets from one place in your application to another, you just shove your mutable state blob into every last part of your application and the framework does the rest.
But what you lose in return is the ability to control when state should change and sight of where changes come from. In the case of POJO state implementations like AngularJS 1 it also means you have to constantly diff the state against what you've last rendered to be able to respond to changes nobody told you about.
AngularJS 1 actually tried to optimise this a bit but ultimately it needed to pretty much control everything asynchronous in order for that optimisation to work and more often than not that resulted in hapless beginners wondering why their changes aren't always reflected in the UI (answer: because nobody told Angular it should check).
So in other words, your state consists of big balls of mud that may change shape without notice and if you pass one of them to any piece of code you must expect it to do just that without any way to tell until it happens (and good luck trying to figure out where it happened exactly).
Compare this to the "one-way data flow" React made popular: your state is a bunch of impenetrable rocks that roll into your application, which can't modify them but can do whatever it wants in response to them (e.g. push pixels around on the screen). If the application wants different rocks, it needs to explicitly tell wherever they came from that they should be different, at which point the application will be fed a different (or maybe identical) set of impenetrable rocks again.
In a word this is basically the difference between mutability and immutability, taken to the extreme. Although there's nothing in React forcing you to use immutable data structures, the one-way data flow assumes everything it's fed is immutable unless you say otherwise, and you pass in callbacks to be notified when state should change.
On the other hand, in two-way binding your state is mutable and extremely malleable by definition, and thus the implicit expectation for every operation is that it may have changed the state.
As a side-note: React actually has a dirty little secret called "context" which is the equivalent of thinking with portals: instead of passing ALL the state into your ENTIRE application's root, you pass the state container to a magical Pez dispenser that wraps your application root and then each component can be wrapped in a container that knows about the dispenser and asks it for a specific part of the state. That's how React-Redux works among other things and it's not entirely unlike dependency injection (except it doesn't happen globally but only in the context of the specific instance of the application).
Not sure on macOS, bindings may still exist there.