-1

我已经阅读了很多关于闭包和原型的文章......但我仍然有一些问题。我从这篇文章开始:http: //blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx

我的问题是要公开公共方法:

这个方法是:

// Closure implementation
function Pixel(x, y){
  this.x = x;
  this.y = y;
  this.getX = function(){
    return this.x;
  }
  this.getY = function(){
    return this.y;
  }
  this.setX = function(value){
    this.x = value;
  }
  this.setY = function(value){
    this.y = value;
  }
}

与此不同:

// Closure implementation
function Pixel(x, y){
  this.x = x;
  this.y = y;
    return {
        getX : function(){
            return this.x;
          },
        getY : function(){
            return this.y;
          },
        setX : function(value){
            this.x = value;
          },
        setY : function(value){
            this.y = value;
          }
    }
}

哪一个是最好的?为什么?

最后一个问题:从上面的基准测试来看,有没有办法使用闭包来获得与原型相似的性能?

发送

4

2 回答 2

1

那么没有“更好”的实现。

第二个选项将产生错误,因为您不能对其调用 new 因此this将引用窗口(或定义/调用函数时您所在的任何范围),所以不要使用它

第二个选项可以像这样使用闭包:

function Pixel(x, y){
  this.x = x;
  this.y = y;
  var that = this;
    return {
        getX : function(){
            return that.x;
          },
        getY : function(){
            return that.y;
          },
        setX : function(value){
            that.x = value;
          },
        setY : function(value){
            that.y = value;
          }
    }
}

但这开始变得非常丑陋,与隐私问题不兼容,prototype并且在我看来过于重视隐私问题。

于 2013-02-06T17:54:39.020 回答
0

有很多话要说。首先,这种get/set机制在 Javascript 中很少适用。这个 Java 结构必须确保所有对数据的访问都是通过公共方法而不是通过私有属性。Javascript 世界根本不在乎。

但是,假设您确实想要 Pixel 对象,并且想要封装它们xy数据,例如公开以下两个函数:

toString(); // String (a representation of this Pixel)
offset(deltaX, deltaY); // Pixel (a new Pixel shifted by deltas from this one)

然后你可以这样做:

var PixelA = function(x, y) {
    this.x = x; this.y = y;
    this.toString = function() {
        return "(" + this.x + ", " + this.y + ")";
    };
    this.offset = function(deltaX, deltaY) {
        return new PixelA(this.x + deltaX, this.y + deltaY);
    };
};

或者你可以这样做:

var PixelB = function(x, y) {
    this.toString = function() {
        return "(" + x + ", " + y + ")";
    };
    this.offset = function(deltaX, deltaY) {
        return new PixelB(x + deltaX, y + deltaY);
    };
};

或者你可以这样做:

var PixelC = function(x, y) {
    this.x = x; this.y = y;
}
PixelC.prototype.toString = function() {
    return "(" + this.x + ", " + this.y + ")";
};
PixelC.prototype.offset = function(deltaX, deltaY) {
    return new PixelC(this.x + deltaX, this.y + deltaY);
};

注意:所有内容均未经测试。)

PixelA相当幼稚。我们的数据没有被封装;任何人都可以直接访问或改变我们的内部xy属性。而且它是内存密集型的;PixelA 的每个实例都有自己的toStringoffset函数副本。

PixelB解决第一个问题。内部数据存储在构造函数生成的闭包中。toStringand函数可以访问这些offset变量,但外部无法直接看到它们。但它并不能缓解第二个问题。

PixelC解决第二个问题。由于toStringoffset函数存储在原型中,因此实例不会被它们的重复副本乱扔。但是xy属性再次公开,第一个问题又回来了。

我不知道选项 D。我相信您需要在封装内部状态和让原型函数访问该状态之间做出选择。您可以通过许多不同的语法扭曲来尝试解决此问题;但没有一个真正解决这个根本问题。您可以在任一方向执行某些优化,但问题是根本性的。

我很想被证明是错误的。

至于性能问题:基于闭包的构造不可能都像基于原型的构造一样快。想想在基于闭包的版本中为每个实例分配所有这些属性必须完成的所有工作,这些工作根本不需要在基于原型的版本中完成。现在,基于闭包的属性访问可能会更快......

于 2013-02-06T19:10:31.013 回答