使用getter和setter在JavaScript中封装

时间:2017-11-21 20:09:20

标签: javascript encapsulation setter getter

我意识到这已经被问到但已经研究过并且失败了 - 抱歉!

我想尽可能简单地在JS中实现封装。我意识到班里的任何'var'都是私有的。

我只是不确定如何获取和设置任何私有var的值。在下面的示例中,GETTING和SETTING'color'的接口方法不起作用,因为这些函数无法访问对象的私有'color'属性。我找不到一个明确的例子来告诉我如何实现它。

我甚至不确定使用'.prototype'是将这些方法添加到班级的最佳方法。

谢谢!

<button onclick="testOOP()">Click me</button>

<script>
//<!-- 
function testOOP(){
var v1 = new vehicle(4, "red"); //setting new values during instantiation
var v2 = new vehicle(2, "blue");
showVehDetails(v1);
showVehDetails(v2);
v2.wheels=1;            //demonstrating no encapsulation
showVehDetails(v2);
v2.setcolour("orange");     //using an interface - fails
showVehDetails(v2);
}

    function showVehDetails(v){
        document.write("This vehicle is " + v.getcolour() + " and has " + v.getwheels() + " wheels.<br/>");
    }

    //*************'vehicle' - Class definition**************
    function vehicle(thewheels, thecolour){
        this.wheels = thewheels;            //public property
        var colour = thecolour;             //private property
    }   
    vehicle.prototype = {
        constructor: vehicle,
        getcolour: function(){
            return this.colour;         //but how to create a GETTER for colour?
        },
        getwheels: function(){
            return this.wheels;
        },
        setwheels: function(newwheels){
            this.wheels = newwheels;
        },
        setcolour: function(newcolour){   //and how to create a SETTER for colour?
            this.colour = newcolour;
        }
    }
    //************End class definition************************
   //-->
 </script>

1 个答案:

答案 0 :(得分:3)

构造函数中声明的任何var都不会存在于该构造函数之外。您需要将事物附加到 this ,以便原型方法能够看到它。 JavaScript没有私有成员的概念。

function Vehicle(thewheels, thecolour){
  this.wheels = thewheels;
  this.colour = thecolour;
}

Vehicle.prototype = {
  getColour: function() {
    return this.colour;
  }
  // etc
};

...但是你必须问问自己,围绕这些成员设置getter / setter会有什么好处?在JavaScript中使用getter / setter模式非常罕见。通常你只是创建公共成员。对成员使用诸如_前缀之类的东西是表示“我知道这是可访问的,但你不应该直接修改它”的典型方式。

如果你确实想让事情变得“私密”,你需要做一些带闭包的技巧:

function Vehicle(theWheels, theColor) {
  return {
    getColour: function() { return theColor; },
    setColour: function(value) { theColor = value; }
  };
}

...但这种方法的缺点是每个Vehicle对象都有自己的这些函数副本;你没有获得原型的记忆效益。

<强>更新

另外值得注意的是:如果你想通过包装方法来触发更改成员的逻辑,那么在现代JS中有更好的方法来创建getter和setter:

function Vehicle(theWheels, theColor) {
  this._wheels = theWheels;
  this._color = theColor;
}

Vehicle.prototype = {
  get color() { return this._color; },
  set color(value) { this._color = value; console.log('Changed color'); },

  get wheels() { return this._wheels; },
  set wheels(value) { this._wheels = value; }
}

调用者只需像普通属性一样访问.wheels.color,它就会调用你的方法。