8

我正在使用对象文字来创建带有方法的对象。
这里举一个简单的例子。

var SizeManager = {
    width : 800,
    height : 600,
    ratio : this.width / this.height,
    resize : function (newWidth) {
        width = newWidth;
        height = newWidth / ratio;
    }
}

我的问题是 SizeManager.ratio 返回“ NaN ”。我很确定这是一个初始化问题。
有没有办法获得正确的比率值?
有没有办法将协构函数或初始化程序分配给对象文字?
定义构造函数对象是唯一的方法吗?

编辑:当然 SizeManager 是理想的单例(只有一个对象),这就是我使用对象文字的方式。

4

3 回答 3

24

是的,这是一个初始化问题。this在您使用它时不引用您的SizeManager对象。(对象初始值设定项不会更改 的值this。)this由您调用函数的方式设置,并且在整个函数调用中具有相同的值。您没有在那里调用任何函数,因此this在该代码开始之前它具有的任何值。

(我在ratio本文最后从您的具体示例中指出了一些内容,但首先让我们为您提出的一般情况介绍一些选项。)

丹尼尔在制作函数方面给了你很好的指导,ratio但他似乎没有意识到你想要改变宽度。或者,如果width并且height不会改变,只需在之后计算:

var SizeManager = {
    width : 800,
    height : 600,
    resize : function (newWidth) {
        this.width = newWidth;
        this.height = newWidth / this.ratio;
    }
};
SizeManager.ratio = SizeManager.width / SizeManager.height;

(旁注:我已添加this.到您引用的属性中resize。它们在您的原始文件中丢失,但它们是必需的。没有它们,您将面临隐式全局变量的恐怖,这是一件坏事( tm) .)

当然,您可以将所有这些封装到工厂中:

function makeSizeManager(width, height) {
    return {
        width : width,
        height : height,
        ratio : width / height,
        resize : function (newWidth) {
            this.width = newWidth;
            this.height = newWidth / this.ratio;
        }
    };
}
var SizeManager = makeSizeManager(800, 600);

...但是您也可以将其设为实际的构造函数,这样您就不会创建大量重复(但相同)的resize函数:

function SizeManager(width, height) {
    this.width = width;
    this.height = height;
    this.ratio = width / height;
}
SizeManager.prototype.resize = function (newWidth) {
    this.width = newWidth;
    this.height = newWidth / this.ratio;
};
var aSizeManagerInstance = new SizeManager(800, 600);

(请注意,我在最后一个上稍微更改了名称。)

最后一点:在您的具体示例中,您实际上根本不需要存储ratio,您可以这样做:

var SizeManager = {
    width : 800,
    height : 600,
    resize : function (newWidth) {
        var ratio = this.width / this.height;
        this.width = newWidth;
        this.height = newWidth / ratio;
    }
};

但这只是针对那个特定的例子,因此上面的讨论是关于一般情况的。

于 2010-09-22T14:23:57.340 回答
5

如果您希望它根据对andratio的更改而更改,那么您的属性实际上应该是一种方法:widthheight

var SizeManager = {
    width : 800,
    height : 600,
    ratio : function() {
      return this.width / this.height;
    },
    resize : function (newWidth) {
        width = newWidth;
        height = newWidth / ratio;
    }
}

此外,您可能希望在方法中引用this.widthandthis.height而不是widthand 。heightresize

于 2010-09-22T14:23:02.337 回答
0

在对象字面量中,this仅在对象字面量位于函数内部时才指代对象字面量本身。您可以尝试这样的事情而不是对象文字;this将引用您在函数内部和外部创建的对象。

var SizeManager = new function(){
    this.width = 800;
    this.height = 600;
    this.ratio = this.width / this.height;
    this.resize = function (newWidth) {
        this.width = newWidth;
        this.height = newWidth / this.ratio;
    }
}

这将适用于单例模式。如果您需要多个 SizeManager,请将其设为构造函数而不是对象。

function SizeManager (w, h){
  w && (this.width=w);
  h && (this.height=h);
  this.ratio = this.width / this.height;
}
SizeManager.prototype={ 
  width: 800,
  height: 600,
  resize: function (newWidth) {
    this.width = newWidth;
    this.height = newWidth / this.ratio;
  }
}
于 2010-09-22T14:28:20.520 回答