0

我是原型新手,我只是做了一个不起作用的简单示例。从下面的代码可以看出我想要什么 - 一个计数器。但由于某种原因,输出始终是5,我猜是在bind制作对象的深层副本,this然后将其绑定到函数。有一个明显的解决方案,我将所有内容都公开,但我想知道是否有更优雅的解决方案。(或者你可以纠正我并告诉我没有深拷贝,但有其他错误)。文档对我没有帮助。

编码:

<!DOCTYPE html>
<html>
    <body>
        <input type="button" value="click" onclick="javascript: doTest();" />
        <div id="canvas"></div>
        <script>
            var ClassA = function (position, element) { // constructor
              this.field1 = position;
              this.target = element;
            };

            ClassA.prototype = function () {
              // private functions
                var _aPrivateMethod = function(){
                    console.log(this);
                    this.field1 += 1;
                    return this.field1;
                };

                var _aPublicMethod = function(){
                    this.target.innerHTML = _aPrivateMethod.bind(this)();
                };

                return { // interface
                    constructor: ClassA,
                    aPublicMethod : _aPublicMethod
                };
            }();

            function doTest() {
                var obj = new ClassA(4, document.getElementById('canvas'));
                obj.aPublicMethod();
            }
        </script>
    </body>
</html>
4

1 回答 1

1

这里有一些问题。首先你doTest每次都打电话。每次单击都会创建一个新对象,因此无法增加field1.

据我了解,您想field1保持私密性。在您初始化它的方式中,它不能是私有的。您可以执行以下操作:

function Person() {
   var counter = 0;
   this.increment = function () {
       return ++counter;
   }
}

这样你就不counter能从函数范围之外访问。

另一个问题是您没有使用正确的上下文调用私有方法。你应该使用_aPrivateMethod.call(this)pimvdb 提到的。

下面是一个例子:

function Person() {

    var age = 0;

    function incrementAge() {
        return ++age;
    }

    function eatCake() {
        console.log('Yey. I\'ll eat cake!');
    }

    this.birthday = function () {
        eatCake();
        return incrementAge();
    }
}

var p = new Person();
p.birthday(); //'Yey. I'll eat cake!', returns 1
p.birthday(); //'Yey. I'll eat cake!', returns 2

这样eatCakeincrementAge并且age由于功能范围而都是私有的。示例中的坏处是我声明函数的方式birthday。将为每个实例Person创建一个新副本。正确的方法是:

Person.prototype.birthday = function () { ... }

我的声明不是这样的,因为我想使用私有数据成员。实际上不仅仅是函数(age, eatCake, incrementAge)的本地私有。无法从原型中声明的函数访问它们,这就是为什么对于上面的示例,我选择了这种方法。

于 2012-11-27T13:33:36.390 回答