Angular has some specific abstractions, like directives and transclusion, plus some "general" OOD abstractions, like factories and services.
The problem is that those abstractions are not really good.
- Dependency injection lacks some functionality you will need sometime.
- Directives are overloaded with responsibilities (ever wonder why and when you should use isolated scope? Yeah, that's only the tip of the iceberg).
- Directives are not really components. They are the "legacy" from those times, when angular was just an "HTML compiler"
Modules are not real modules.
No CommonJS/AMD. No custom lazy loading. No namespaces.
You can use modules only to specify the dependency graph and get rid of specifying the correct file order for injecting scripts (which is not a problem anyway if you are using component-based structure and, for example, browserify).
$scope is "transparent" and inherited by default.
Inheritance is known to be an antipattern in OOD. (Proof?)
You MUST know the cases, when it can be useful.
Angular forces you to get rid of this inheritance all the time.
Bidirectional binding is unpredictable and hard to control (unless you know that you MUST control it).
Pair it with the transparent scope - and you get the "referential hell", when you cannot control WHAT changes the value in your current component.