Javascript OOP - 从原型setter访问方法

时间:2013-01-02 02:00:12

标签: javascript oop

尝试运行以下代码时出现“未定义”错误。它发生在this.xPositionForPageAtIndex(selectedPageNumber)行。当我尝试记录this时,所有实例属性都在那里,除了函数。

function Gallery(div) {
    this.count = 5;
    this.pageWidth = 500;
    this.selectedPage = 1;

    this.xPositionForPageAtIndex = function(pageIndex) {
        if (pageIndex < 1 || pageIndex > this.count) {
            return 0.0;
        }

        return (pageIndex - 1) * this.pageWidth;
    }
}

Gallery.prototype = {
    set selectedPage(selectedPageNumber) {
        var page = this.pages[((selectedPageNumber) + 1)];

        if (!page.classList.contains("animate")) {
            page.classList.add("animate");
        }

        if (!page.classList.contains("final")) {
            page.classList.add("final");
        }

        console.log(this);

        this.binder.setAttribute("-webkit-transform", "translateX(" -this.xPositionForPageAtIndex(selectedPageNumber) + "px)");

        this.selectedPage = page;
    }
}

我对Javascript OOP有点新,但我认为我真的不懂足够的术语来正确研究这个答案。

1 个答案:

答案 0 :(得分:1)

Concat问题

就行了,你说你遇到了麻烦,而不是加号:

"translateX(" -this.xPositionForPageAtIndex(selectedPageNumber)

应该是

"translateX("  + this.xPositionForPageAtIndex(selectedPageNumber)

通过将公共方法放入原型

进行优化

此外,将xPositionForPageAtIndex放在原型中可能是个好主意,因为它不依赖于任何私有字段。任何公共函数(这意味着它不依赖于私有字段)都可以进入原型。这样,对于您正在创建的对象的每个实例,都不会有该函数的副本。

根据您的代码,我认为您没有足够的Gallery个实例来解决这个问题,但这仍然是一个很好的做法。

另一方面,如果你的函数依赖于某种私有字段,那意味着它是一个特权函数,它不能进入​​原型。像这样:

function Gallery(someParam){
    //this is a private variable
    var hiddenVar = someParam + "bar";

    // this is a privileged method: publicly accessible, but
    // can "see" private variables
    this.showHidden = function() {
        return hiddenVar
    };      
};
var gal = new Gallery("foo");
gal.hiddenVar; // undefined
gal.showHidden(); // "foobar"

意外的无限递归

更大的问题是以下一行:

this.selectedPage = page;

该行位于属性selectedPage的设置者中。

该行使selectedPage以递归方式调用自身,并且只能以RangeError结尾。

根据函数编写它会使它更清晰一些,所以这就是正在发生的事情:

var a = {
    foo: function(param){
        // do some stuff
        this.foo(4);
    }
};

调用a.foo(2)会产生RangeError

由于ES5设置器的工作方式,它隐藏了一点。以下是使用setter的结果:

var a = {
    set foo(){
        // do some stuff
        this.foo = 3;
    }
};

调用a.foo = 2将导致RangeError,因为递归调用了setter函数。

希望有所帮助。如果你还没有检查过道格拉斯·克罗克福德,你就是他。有一些很好的讲座可以帮到你很多。