Here's my version that detects and handles isolate scopes correctly and stops as soon as it finds the element. Angular's .scope() and .isolateScope() functions use the jquery .data() object and if a scope is not found, they search up through the parent nodes of the element. We're already searching through all nodes, so it's a lot more efficient to skip the parent search and inspect .data() directly.
const findScopeElement = $scope => {
const {$id, $root} = $scope;
let result;
const isolate = $scope !== $root &&
Object.getPrototypeOf($scope) === Object.getPrototypeOf($root);
const cls = isolate ? '.ng-isolate-scope' : '.ng-scope';
const search = (i, e) => {
const data = $(e).data();
const scope = isolate ? data.$isolateScope : data.$scope;
if(scope && scope.$id === $id) {
result = e;
return false;
}
};
$(cls).each(search);
if(!result) {
// could be an attribute directive
$(`:not(${cls})`).each(search);
}
return result;
}