Javascript - closure - 语法 - 公共成员

时间:2013-02-06 17:52:30

标签: javascript performance methods closures

我已经阅读了很多关于闭包和原型的文章......但我还是有一些问题。 我从这篇文章开始: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;
          }
    }
}

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

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

TX

2 个答案:

答案 0 :(得分: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不兼容,我认为对隐私问题过于重视。

答案 1 :(得分: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解决了第一个问题。内部数据存储在构造函数生成的闭包中。 toStringoffset函数可以访问这些变量,但外面的任何内容都无法直接看到它们。但它没有解决第二个问题。

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

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

我很想被证明是错的。

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