As has been said, javascript doesn't have protected variables.
In the 10 years since this question was written, Typescript has become a thing, and people interested in OOP in javascript should check it out! It does support protected variables.
That said, I'd like to throw my hat into the ring and provide a method for emulating protected variables using plain javascript, since this is a top Google search result and the top-voted answer as of writing doesn't really fit the bill.
// Declare objects within an anonymous function to limit access.
var objectRefs = (function() {
// This is the object we want to inherit from.
function Base(param1, _protected) {
var _public = this;
var _protected = _protected || {};
var _private = {};
// Declare some variables
_public.shared = "Anyone can access this!";
_protected.inherited = "This is protected";
_private.secretVar = "Children cannot access this.";
// Let's try a few functions.
_public.foo = function() {
// We can access protected and private functions here. This would
// not be possible if we attached it to the prototype.
console.log(_protected.inherited);
console.log(_private.secretVar);
_private.secret();
};
_protected.bar = function() {
// One thing to watch out for: private functions called after
// construction do NOT have access to the object via 'this'. This is
// masked by the fact that I assigned it to the '_public' var.
// More reading: https://stackoverflow.com/q/20279484/3658757
console.log(_public.shared);
};
_private.secret = function() {
// The same warning in _protected.bar applies here too.
console.log(_public.shared);
};
}
// Inherits from Base
function Derived(param1, _protected) {
var _public = this;
var _protected = _protected || {};
var _private = {};
// Inherit (ready for the magic?)
Base.call(this, param1, _protected);
// Since we passed a reference to the "_protected" object as an argument
// to the Base object, it has been attaching all of its protected
// variables to it. We can now access those variables here:
// Outputs "This is protected"
console.log(_protected.inherited);
// We can also access protected functions:
_protected.bar();
// We can even override protected variables and functions.
_protected.inherited = "New value!";
// We cannot access private variables belonging to Base.
// This fails:
// console.log(_private.secretVar);
}
// We don't want to allow public access to the constructors, because this
// would let outside code pass in a '_protected' var. Instead, we create new
// objects that accept all params minus '_protected', and inherit from the
// target object.
return {
Base: function(param1) {
Base.call(this, param1);
},
Derived: function(param1) {
Derived.call(this, param1);
}
};
}());
// Assign the constructors to variables for clarity.
var Base = objectRefs.Base;
var Derived = objectRefs.Derived;
// This is how you construct the object.
var newDerived = new Derived("param1");
// Public functions are accessible.
newDerived.foo();
// Protected functions are not. These fail:
// newDerived.bar();
// newDerived.protected.bar();
So that was fun! This structure makes protected variables function the way you'd expect: inheriting objects can access them, but they're inaccessible from the outside.
For reference, here's what the above code looks like in Typescript:
class Base
{
// Declare some variables
public shared: string = "Anyone can access this!";
protected inherited: string = "This is protected";
private secretVar: string = "Children cannot access this.";
constructor(param1: string) {
// We're not using param1; it's only there as an example.
// If we didn't need any constructor code, we could leave this out.
// Note that Typescript has type checking (hence the name)
}
// Let's try a few functions.
public foo(): void {
console.log(this.inherited)
console.log(this.secretVar)
this.secret();
}
protected bar(): void {
console.log(this.shared);
}
private secret(): void {
console.log(this.shared);
}
}
class Derived extends Base {
constructor(param1: string) {
super(param1);
// Outputs "This is protected"
console.log(this.inherited);
// We can also access protected functions:
this.bar();
// We can even override protected variables and functions.
this.inherited = "New value!";
}
}
// This is how you construct the object.
var newDerived = new Derived("param1");
// Public functions are accessible.
newDerived.foo();
// Protected functions are not. This fails:
// newDerived.bar();
Structurally, this is much clearer. As you're coding, you'll be given an error if you try to access a protected variable from outside the object.
But be aware: if you need the compiled javascript to limit outside access to those variables, Typescript won't do that for you. Here's what the compiled output looks like:
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Base = (function () {
function Base(param1) {
this.shared = "Anyone can access this!";
this.inherited = "This is protected";
this.secretVar = "Children cannot access this.";
}
Base.prototype.foo = function () {
console.log(this.inherited);
console.log(this.secretVar);
this.secret();
};
Base.prototype.bar = function () {
console.log(this.shared);
};
Base.prototype.secret = function () {
console.log(this.shared);
};
return Base;
}());
var Derived = (function (_super) {
__extends(Derived, _super);
function Derived(param1) {
var _this = _super.call(this, param1) || this;
console.log(_this.inherited);
_this.bar();
_this.inherited = "New value!";
return _this;
}
return Derived;
}(Base));
var newDerived = new Derived("param1");
newDerived.foo();
As you can see, not only are the protected variables public, but so are the private ones!
If you need encapsulation in the browser, then you'll have to stick with workarounds like I outlined in the first chunk of code. If you're using encapsulation to help you reason about the code, Typescript is the way to go.