Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the @private annotation actually do in Google Closure JavaScript code?

When I put a comment above my variable or function with @private in it what is it actually doing? I have looked at the documentation but I'm still not sure.

goog.provide('myproject');

/** @private */
myproject.foo = "bar";

I can still access it when I open up chrome's development tools (myproject.foo). And...

goog.require('myproject');

window.addEventListener('load', function() {
    //this works.
    document.body.textContent = myproject.foo;
});

The above code still set's the bodies textContent to equal "bar", even when compiled. So what does @private actually do?

like image 833
Zaucy Avatar asked Jul 06 '12 19:07

Zaucy


2 Answers

The access control annotations @private, @protected, and @public are directives for the Closure Compiler that help developers enforce the desired level of visibility for properties and functions.

To emit warnings for access violations use the Compiler flag:

  • --jscomp_warning=visibility

To emit errors for access violations use the Compiler flag:

  • --jscomp_error=visibility

Access control annotations are enforced on a per file basis, meaning that any properties annotated @private or @protected may be accessed anywhere within the same file. Also note that the compiler removes these annotations from the compiled code since they are not part of the JavaScript language.

Example

file1.js

goog.provide('ns1');

/**
 * Global private variable.
 * @private
 */
ns1.global = 'foo';
alert('ns1.global = ' + ns1.global); // OK in same file.


/** @constructor */
ns1.Constructor = function() {
  /** @private */
  this.secret_ = ns1.global;
};

ns1.instance = new ns1.Constructor();
alert(ns1.instance.secret_); // No warning in same file.

file2.js

goog.provide('ns2');

goog.require('ns1');

alert('ns1.global = ' + ns1.global); // Not allowed.

ns2.instance2 = new ns1.Constructor();
alert(ns2.instance2.secret_); // Not allowed.

With the flag --jscomp_error=visibility set, Closure Compiler emits the following errors.

ERROR - Access to private property global of ns1 not allowed here.
alert('ns1.global = ' + ns1.global);
                        ^
ERROR - Access to private property secret_ of ns1.Constructor not allowed here.
alert(ns2.instance2.secret_);
      ^

See Visibility (private and protected fields) in the Google JavaScript Style Guide.

like image 67
Christopher Peisert Avatar answered Sep 24 '22 07:09

Christopher Peisert


cpeisert implied this in his answer, but just to be explicit: these visibility annotations don't modify your output at all.

Marking a function as @private does not hide it or make it any less accessible in the resulting code than the Compiler normally would, and any third-party code that you introduce at runtime will be able to invoke such functions.

The only access protection offered by these annotations is against code that you compile in with them.

like image 44
Ross Avatar answered Sep 24 '22 07:09

Ross