All the functions are shown below work in a similar way but they all have a few subtle differences. Here are a few differences that I found -
elm.isPresent() -
It is an extension of ElementFinder and so waits for Angular to settle on a page before executing any action.
It works when elm is an element(locator) or ElementFinder and not ElementArrayFinder. If multiple elements are returned using the locator specified then the first element is checked if it isEnabled() in the DOM. It doesn't take any parameter as input.
Works best with Angular pages and Angular elements.
First preference to use whenever there's a necessity to search out if an element is present.
elm.isElementPresent(subLoc) - (When there is a sub locator to elm)
It is an extension of ElementFinder and so waits for Angular to settle on the 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. (the only difference between this and the elm.isPresent())
Works best with Angular pages and Angular elements.
First preference to use whenever there's a necessity to see if a sub-element of a parent is present.
browser.isElementPresent(element || Locator) -
It is an implementation of a web driver and so doesn't wait for angular to settle.
Takes a locator or an element as a parameter and uses the primary result if multiple elements are placed using constant locator.
Best used with Non-Angular pages.
First priority to use when testing on non-angular pages.
All of the above points identifies the existence of an element in DOM and returns a Boolean value. Though angular and non-angular features don't affect the usage of these methods, there's an added advantage when the method waits for angular to settle by default and helps avoid errors just in case of angular like element not found or state element reference exceptions, etc.