Javascript-闭包-语法-公共成员

Javascript - closure - syntax - public members

本文关键字:成员 语法 闭包 Javascript-      更新时间:2023-09-26

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

没有"更好"的实现了。

第二个选项将产生错误,因为您无法对其调用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不兼容,并且在我看来过于重视隐私问题。

有很多话要说。首先,这种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的每个实例都将具有CCD_ 10和CCD_。

PixelB解决了第一个问题。内部数据存储在构造函数生成的闭包中。toStringoffset函数可以访问这些变量,但外部没有任何东西可以直接看到它们。但这并不能缓解第二个问题。

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

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

我希望被证明是错的。

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