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

2

6

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?

Moreau answered 6/7, 2012 at 19:23 Comment(0)
T
6

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.

Thong answered 6/7, 2012 at 21:55 Comment(3)
In closurebuilder I set --compiler_flags="--jscomp_error=visibility" but nothing is changing. No compiler errors. Great answer btw! :) Didn't know those resources existed.Moreau
@Saucy, to get the visibility errors/warnings, you also need to set --compiler_flags="--warning_level=VERBOSE"Thong
Thank you very much, @cpeisert ! You've been much help. :)Moreau
M
1

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.

Magic answered 9/7, 2012 at 10:13 Comment(1)
I was wondering if it was possible to use @private and @protected for a better compression (eg.: minify the property names that aren't used from the outside - in simple optimizations). Well, maybe in the future.Commercialize

© 2022 - 2024 — McMap. All rights reserved.