Javascript-closure-syntax-public成员

Javascript-closure-syntax-public成员,javascript,performance,methods,closures,Javascript,Performance,Methods,Closures,我已经读了很多关于闭包和原型的文章…但是我仍然有一些问题。 我从这篇文章开始: 我的问题是公开公共方法: 这种方法是: // 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 = fu

我已经读了很多关于闭包和原型的文章…但是我仍然有一些问题。 我从这篇文章开始:

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

这种方法是:

// 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,因此
将引用窗口(或定义/调用函数时所处的任何范围),因此不要使用它

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

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;
          }
    }
}

但这开始变得非常丑陋,与原型不兼容,而且在我看来,隐私问题太重要了。

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

但是假设您确实想要像素对象,并且您想要封装它们的
x
y
数据,比如说,公开以下两个功能:

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);
};
或者你可以这样做:

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);
};
或者你可以这样做:

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
相当幼稚。我们的数据没有封装;任何人都可以直接访问或修改我们的内部
x
y
属性。而且它是内存密集型的;PixelA的每个实例都有自己的
toString
offset
函数副本

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

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

我不知道选项D。我相信您需要在封装内部状态和让原型函数访问该状态之间做出选择。为了解决这个问题,你可以经历很多不同的综合性扭曲;但没有人真正解决这一根本问题。您可以在任一方向执行某些优化,但问题是根本的

我希望被证明是错的


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

这些示例并不等效,也没有真正使用闭包。以第二个示例为例,运行
(新像素(4,2)).getX()
。返回值将是
未定义
,而不是
4
。假设您修复了这个问题,最大的区别在于,在第二种情况下,实例化(返回)对象不会继承自
Pixel。prototype
和类似
obj instanceof Pixel
的测试将失败。第一个示例是“类”定义,第二个示例根本不起作用。这就是区别。如果您执行
var o=new Pixel(10,20)
,则
o.getX()
将是返回的对象,但
x
y
将是未定义的。您可以使用
new
调用任何函数。它只需要返回一个对象,如果不返回,则返回
这个
。此外,使用
var
语句的第一个方法将作为创建“私有字段”的更好方法。