在javascript中声明受保护的变量

时间:2011-09-23 18:57:21

标签: javascript oop

我如何声明受保护的变量。我在这里举个例子

// Constructor
function Car(){

   // Private Variable
   var model;
}

// Public variable
Car.prototype.price = "5 Lakhs";

// Subtype
function Indiancar(){
}

// Prototype chaining
Indiancar.prototype = new Car();


// Instantiating Superclass object
var c = new Car();

// Instantiating subclass object
var ic = new Indiancar();

在这里我希望有一个可以作为ic.variabl访问的变量,它也存在于汽车类中。

3 个答案:

答案 0 :(得分:6)

你会做这样的事情:

var Base = function()
{
    var somePrivateVariable = 'Hello World';

    this.GetVariable = function()
        {
            return somePrivateVariable;
        };

    this.SetVariable = function(newText)
        {
            somePrivateVariable = newText;
        };
};

var Derived = function()
{
};

Derived.prototype = new Base();

var instance = new Derived();

alert(instance.GetVariable());
instance.SetVariable('SomethingElse');
alert(instance.GetVariable());

假设我正确地理解了你的问题。

编辑:使用真正的'私人'变量进行更新。

答案 1 :(得分:4)

有一种方法可以在JavaScript中定义受保护的变量:

javascript中的构造函数可能会返回任何对象(不一定是 this )。可以创建一个构造函数,它返回一个代理对象,该代理对象包含“真实”实例对象的“真实”方法的代理方法。这可能听起来很复杂,但事实并非如此;这是一段代码片段:

var MyClass = function() {
    var instanceObj = this;
    var proxyObj = {
        myPublicMethod: function() {
            return instanceObj.myPublicMethod.apply(instanceObj, arguments);
        }
    }
    return proxyObj;
};
MyClass.prototype = {
    _myPrivateMethod: function() {
        ...
    },
    myPublicMethod: function() {
        ...
    }
};

如果我们定义用于命名受保护方法的约定,那么代理创建可以是自动化的。我创建了一个完整的小库:http://idya.github.com/oolib/

答案 2 :(得分:0)

如前所述,javascript 没有受保护的变量。

这个问题写了 10 年,Typescript 已经成为一个东西,对 javascript 中的 OOP 感兴趣的人应该去看看!它确实支持受保护的变量。

也就是说,我想把我的帽子扔进戒指并提供一种使用普通 javascript 模拟受保护变量的方法,因为这是一个顶级的 Google 搜索结果,而 the top-voted answer 在撰写本文时并不是真的符合要求。

// 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();

那很有趣!这种结构使受保护的变量以您期望的方式发挥作用:继承对象可以访问它们,但无法从外部访问它们。

作为参考,上面的代码在 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();

在结构上,这要清楚得多。在编写代码时,如果您尝试从对象外部访问受保护的变量,则会出现错误。

但请注意:如果您需要编译后的 javascript 来限制对这些变量的外部访问,Typescript 不会为您执行此操作。编译后的输出如下所示:

"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();

如您所见,不仅受保护的变量是公开的,私有变量也是如此!

如果您需要在浏览器中进行封装,那么您必须坚持使用我在第一段代码中概述的解决方法。如果您使用封装来帮助您推理代码,那么 Typescript 是您的最佳选择。