All of these work very similar but with subtle differences. Those differences are:-
elm.isPresent() -
This is an addition to ElementFinder and this waits basically for Angular to settle on page before executing that action.
It works when elm is an element(locator) or ElementFinder and not ElementArrayFinder.
Works best with Angular pages and Angular elements.
1st preference when there is a need to find if an element is present.
elm.isElementPresent(subLoc) - (When there is a sub locator to elm)
This is basically an extension to ElementFinder, and this waits for Angular to settle on page before executing any action.
Used to check the presence of elements that are sub elements of a parent. It takes a sub locator to the parent elm as a parameter. (only difference between this and the elm.isPresent())
Works best with Angular pages and Angular elements.
1st preference when there is a need to check if a sub element of a parent is present.
browser.isElementPresent(element || Locator) -
Is an implementation of webdriver and obviously doesn't automatically wait for angular to settle down.
Takes a locator or an element as a parameter and uses the first result if multiple elements are located using the same locator.
Best used with Non-Angular pages.
1st preference to use for testing non-angular or descent level dynamic pages.
All of the above checks for the presence of an element in DOM and returns a boolean result. Even though angular and non-angular features don't affect the usage of these methods, but its just more developer friendly.
There's an added advantage when the method waits for angular to settle by default and helps avoid errors in case of angular like elementnotfound or stateelementreference exceptions, among others.