使用原型对象时隐藏的信息

Information hiding when using the prototype object

本文关键字:隐藏 信息 对象 原型      更新时间:2023-09-26

在我们的代码库中,我发现许多开发人员使用下划线作为成员变量的第一个字母来阻止公众使用。通常,更好的做法是声明一个对象的方法可以访问的局部变量,但在我们的情况下,这似乎不可能,因为所有方法都是在原型上定义的。下面是一个例子。

MyContrivedWidget = function(container) {
  this._container = jQuery(container);
}
MyContrivedWidget.prototype = {
  draw: function() {
    var link = jQuery(document.createElement('a'))
      .html('some contrived text')
      .attr('href', '#')
      .appendTo(this._container);
  }
}

我们使用原型对象有多种原因,但最引人注目的可能是使用原型链可以方便地继承和重写方法。这对我们来说很好,因为我们在一个平台上有多个产品,它们可能希望在覆盖特定功能的同时重用大量JavaScript。

因此,我的问题是,在不允许本应私有的变量公开访问的情况下,我们如何才能获得原型链的所有好处?

简单地说:ECMAscript第3版不可能使用原型继承或原型链创建"私有"变量。

ES5有点不同。您有像.defineProperties()help这样的方法,它们能够在对象中"隐藏"属性。

但是,即使你隐藏了这些财产,例如,如果知道它们是可用的,你仍然可以访问这些财产。正如您所提到的,ECMAland中唯一真正的隐私是调用闭包。更好的说法是,通过调用函数(context)来使用方法模式,该函数返回一个包含作为属性的方法的对象。这些方法可以访问外部(父)作用域中声明的变量(因为它的上下文关闭在父上下文之上)。之后没有其他对象可以访问这些变量。这看起来像:

var Animal = function( args, priv, shared ) {
    shared = shared || { };
    shared.speed = 2;
    shared.legs = 4;
    shared.name = args.name || 'unknown'; 
    priv = priv || {
        run: function() {
            console.log(shared.name, ' is running ', shared.speed, ' meters');
            return this;
        },
        die: function() {
            console.log(shared.name, ': wwuuaarhhhck.. aahahsd sd..aahsd.....');
            return this;
        }
    };
    return priv;
};
var Dog = function( args, priv, secret ) {
    secret = secret || { };
    priv = Animal( args, priv, secret ) || { };
    priv.addSomeMethod = function() { };
    return priv;
};
var bello = Dog({name: 'Bello'});
bello.die(); // "Bello:  wwuuaarhhhck.. aahahsd sd..aahsd....."

有一些很棒的模式将这一想法扩展到了极致,它们还提供了继承和共享对象+超级方法。这种编程的一个良好开端仍然是Douglas Crockfords的"Javascript:好的部分"。