Angular in the console: get the scope I created (not the whole scope)


I know if I do

angular.element(document.querySelector('<selector-name>')).scope()

I can get the scope. But that gives me everything ($$childTail, $$childHead, etc).

Is there a method that gives me just the $scope elements (variables and functions) that I created on my controller?

One option that, as far as I can tell, provides almost exactly these properties would be to take the difference of the scope that you retrieved (via angular.element(/*...*/).scope()), and that scope's prototype.

Here's a sample function that does that:

function getAssignedScopeProperties(targetScope){
    var targetProto = Object.getPrototypeOf(targetScope);

    var assignedProperties = {};
    for (var prop in targetScope) {
        if (targetScope.hasOwnProperty(prop) && typeof targetProto[prop] === "undefined") {
            assignedProperties[prop] = targetScope[prop];
        }
    }
    return assignedProperties;
}

And then using the function:

var targetElement = angular.element(document.querySelector('<selector-name>'));
var targetProps = getAssignedScopeProperties(targetElement.scope());

Unfortunately, in Angular 1.3.15 this seems to leave the $$watchersCount property. This does not happen in versions 1.3.14, nor 1.3.16, so it was likely a bug in AngularJS for version 1.3.15.

That said, keeping a guard against $$watchersCount (or a blacklist with it) to defend against versions of Angular with such bugs doesn't feel proper to me. Another option to ensure that this doesn't happen is to include a check for prop.charAt(0) !== "$" in the inner-if, but assuming the objective is to keep all values that are assigned in the controller, removing any that the controller defined starting with a $ would certainly be wrong (of course, the person who built the controller assigning to properties starting with $ is wrong, too, but that's neither here nor there).


Older question with unaccepted answer here.

The short answer is no, angular does not provide a method for getting only user created properties. Additionally it is a bit difficult to copy or even convert a $scope object to JSON.

The slightly longer answer is you can create a custom JSON.stringify function to parse the $scope object.

var cleanScope = function(scope, includeFunctions) {
    // custom JSON.stringify function
    // borrowed from: https://stackoverflow.com/questions/24806495/how-to-get-plain-object-from-scope-in-angularjs
    function scopeStringify(key, value) {
        // ignore any key start with '$',
        // and also ignore 'this' key to avoid a circular reference issue.
        if (typeof key === 'string' && (key.charAt(0) === '$' || key === 'this')) {
            return undefined;
        }

        // by default, JSON.stringify will ignore keys with a function as a value
        // pass true as the second param to get back 'function' instead of ignoring
        return includeFunctions && typeof value === 'function' ? 'function' : value;
    }

    return angular.fromJson(JSON.stringify(scope, scopeStringify));
};

// call like so:
console.log('clean $scope: ', cleanScope($scope));

// or pass true as the second param to include functions
console.log('clean $scope: ', cleanScope($scope, true));