Javascript绑定,是否会制作`this`的深层副本?

时间:2012-11-27 13:21:20

标签: javascript environment-variables prototype

我是原型的新手,我只是做了一个不起作用的简单例子。从下面的代码可以看出我想要的东西 - 一个柜台。但由于某种原因,输出总是5,我想bind正在制作this对象的深层副本,然后绑定到该函数。有一个明显的解决方案,我公开一切,但我想知道是否有一个更优雅的解决方案。 (或者你可以纠正我的并告诉我没有深拷贝,但是其他一些错误)。 documentation没有帮助我。

代码:

<!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>

1 个答案:

答案 0 :(得分:1)

以下是一些问题。首先,您每次都致电doTest。每次点击都会创建一个新对象,因此无法增加field1

据我了解,您希望field1是私密的。在初始化它的方式中,它不能是私有的。你可以这样做:

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

这样您就无法从功能范围之外访问counter

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

以下是一个例子:

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

由于功能范围,eatCakeincrementAgeage都是私有的。 示例中的坏处是我声明函数birthday的方式。对于Person的每个实例,将创建一个新副本。 正确的方法是:

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

我的声明与此不同,因为我想使用私人数据成员。实际上,该功能不仅仅是本地的ageeatCakeincrementAge)。 没有办法从原型中声明的函数访问它们,所以这就是为什么上面的例子我选择了这种方法。