The main difference I have found in onion architecture and layered architecture is the location of the abstractions. When I think of layered architecture, the pattern I see a lot of is the interface and the implementation right next to eachother. So let's say you have a IPersonAccessor interface (I'm coming from C#) in MyApp.DAL/Personnel, then you would have a corresponding PersonAccessor class that implements the IPersonAccessor. That's all great as it allows you to switch out the implementation in the tests, but it doesn't really decouple it further than that.
Onion architecture (maybe this is only my own interpretation of onion architecture) allows us to decouple not only class from dependency but also layer from layer. Think about this scenareo, let's say you want to build a desktop version of your web project but using file storage rather than database storage. How would you do this with layered architecture?
In both cases, you would have to create a new version of your DAL. But how would you account for these two different layers in your business layer? In layered architecture, the abstractions are in the DAL, so in order for the business layer to compile, it has to include a reference to the layer in which the abstractions exist. So you can't just swap out the DAL because you need the one with the abstractions. And you can't just duplicate the interfaces in the new DAL for compiled languages because then (besides the duplication of code) just naming something the same doesn't make it the same to the compiler.
The solution is moving the abstractions to the layer that uses it. You would move the abstractions to the business layer. So in the example above, you would have MyApp.BL/Personnel/IPersonAccessor.cs
and then you would have MyApp.DAL.DB/Personnel/PersonAccessor.cs
as well as MyApp.DAL.FileStorage/Personnel/PersonAccessor.cs
Each DAL classes would implement the IPersonAccessor and your IOC container (which most likely exists in your presentation layer) for your app could inject whichever PersonAccessor that it wants. This way, your DAL would reference/depend on the business layer so that it's implementations implement the abstractions which exist in the business layer. Now, the business layer can literally exist in complete isolation as far as dependencies are concerned. You can then swap out your DAL simply by injecting the implementations in the file storage DAL rather than the database DAL and the business layer can remain untouched since the classes of both DALs use the same exact interfaces... the ones that exist in the business layer.
With this new pattern, you get a weird, unfamiliar image. The DAL depends on the business layer. This is why the architectural pattern is thought of as an onion. The DAL is essentially another section of the outer layer. It exists on the same layer as the presentation layer. in fact, I think of this not so much as the DAL layer and the presentation layer... I think of it as the "infrastructure" layer. Inside the infrastructure layer, you have your data access code, your presentation code and other code that communicates with the outside world. Then, underneath this layer, protected from knowing the outside world even exists, is your business layer. It's an onion. one layer is protected from the outside world by another layer of multiple projects/assemblies giving it the likeness of an onion.
So, onion architecture is actually it's own architectural pattern because you have different layers and your interfaces are in a different place... or in other words, they are structured differently which is, by definition, an architectural pattern.
After pondering this architecture, I've started realizing that this really turns your business layer into more of a library that can be thrown in and out of applications since it has no dependencies other than maybe utility libraries like datetime libraries (like in python). This makes your application extremely dynamic because you can easily do things like change your platform, change to micro services, and then maybe change back to a monolith. Yes that's not a likely scenareo by any means, but for huge applications, this can be extremely convenient. All you have to do is re-write your infrastructure logic but your core business logic remains untouched.