Consider a list and let $e,f,g$ be three consecutive elements.
Each element stores a value and has a "forward" pointer to the next element. Additionally, if the list is doubly linked each element also has a "backward" pointer to the previous element.
Consider a singly linked list first. If you want to delete element $f$, then you need to update the pointer of element $e$ (that previously pointed to $f$) to point to $g$. Since you don't know who $e$ is, you have to find it by using an exhaustive search from the beginning of the list. This requires time $\Theta(n)$ in the worst case. Notice that the above discussion holds even if you have a reference to $f$.
Inserting an element in a singly linked list given a reference to the element immediately preceding it can be done in time $O(1)$ (technically, saying that an insertion requires $O(n)$ time is not incorrect since $O(1) \subset O(n)$).
Let's now consider a doubly-linked list. Suppose that you want to delete $f$ and that you have a reference to it. Then you can find $e$ and $g$ in time $O(1)$ by simply following the forward and backward pointers of $f$.
To perform the deletion you can update the forward pointer of $e$ to point to $g$ and the backward pointer of $g$ to point to $e$. This can also be done in constant time.
Inserting an element in a doubly linked list given a reference to the element immediately preceding or following it can be done in constant time.
at a given position
Given how? Insert as $k_{th}$ element? Insert before/after element $e$? in the latter case, the existence of aliases for $e$ may make a difference. $\endgroup$