2012-11-27 139 views
0

我是新来的原型,我只是做了一个简单的例子,不会工作。从下面的代码显而易见我想要的 - 一个计数器。但由于某种原因输出始终为5,我猜bind正在制作this对象的深层副本,然后绑定到该函数。有一个明显的解决方案,我公开所有内容,但我想知道是否有更优雅的解决方案。 (或者你可以纠正我的错误,并告诉我没有深层复制,但有一些其他错误)。 documentation没有帮助我。Javascrtip绑定,它是否创建`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> 
+0

你在哪里使用'.bind'? – pimvdb

+0

分配给'ClassA.prototype'的匿名函数从不使用(或获取)其“self”参数。此外,您应该将立即调用的函数包装在括号中以提高可读性。 –

+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)。 无法从原型中声明的函数访问它们,所以这就是为什么上面的例子中我选择了这种方法。

+0

好吧,我必须等待接受你的回答,但谢谢。我错过了每次启动一个新对象的事实 - 现在工作正常! :) –

+0

太好了。我已经添加了一个继承的例子。我希望这不是太复杂。如果有什么不清楚的地方请让我知道。 –

+0

谢谢,我明白了。对于你的(和将来的读者)信息:在构造函数中声明函数,使它们变成私有的,但是它们的副本将会为每个实例创建。如果有很多人开始,这不太好。 –