2013-04-30 49 views
0

我正在创建一个类,可以在页面上创建任意数量的验证码。我有一个captcha类,用于实例化新的验证码对象c1c2。这里是我的JS:为什么这个javascript对象引用了前一个对象的属性?

$(function(){ 
    var captcha = { 
     parentForm : '', 
     container : '', 
     captcha_input : '', 
     number1 : 0, 
     number2 : 0, 

     createCaptcha : function(form_ID){ 
      var newHtml; 
      this.parentForm = $('#' + form_ID); 
      this.container = this.parentForm.find('.captchaContainer'); 
      this.number1 = this.randomNumber(10); 
      this.number2 = this.randomNumber(10); 


      newHtml = 'What does ' + this.number1 + ' plus ' + this.number2 + ' equal? <b class="required goldenrod" title="Required Field">*</b><br/><br/><input type="text" name="captcha">'; 
      this.container.html(newHtml); 
     }, 

     isValid : function(){ 
      console.log(this.container); 
      this.captcha_input = this.container.find('input[name="captcha"]'); 
      if (this.number1 + this.number2 == this.captcha_input.val()) { 
       this.captcha_input.css('background-color', '') 
       return true; 
      } else{ 
       this.captcha_input.css('background-color', '#FFCCCC') 
       alert(this.number1 + ' plus ' + this.number2 + ' does not equal ' + this.captcha_input.val() + '. Please try again.'); 
       this.captcha_input.focus(); 
       return false; 
      } 
     }, 

     randomNumber : function(max){ return Math.floor(Math.random()*(max+1)); } 
    } 


    var c1 = captcha, 
     c2 = captcha; 

    c1.createCaptcha("form1"); 
    c2.createCaptcha("form2"); 

    $('#form1 input[type="submit"]').click(function() { 
     if(c1.isValid()){ 
      alert('Captcha is valid!'); 
     }else{ 
      return false; 
     } 
    }); 
    $('#form2 input[type="submit"]').click(function() { 
     if(c2.isValid()){ 
      alert('Captcha is valid!'); 
     }else{ 
      return false; 
     } 
    }); 


}); 

而我的HTML:

<form id="form1"> 
    <div class="captchaContainer"></div> 
    <input type="submit"> 
</form> 
<form id="form2"> 
    <div class="captchaContainer"></div> 
    <input type="submit"> 
</form> 

当我点击form1的提交按钮,看起来像isValid方法正在为c2跑,而不是c1像我期待。任何想法为什么这样做?

有几件事情需要注意:

  • 如果我增加更多captcha实例和HTML,每一个提交按钮会就captcha上点击最后一个实例运行isValid
  • 这需要为IE8 +

这里工作是在行动代码的fiddle

任何帮助将不胜感激。谢谢!

+2

c1和c2都是对同一'captcha'对象的引用。 – 2013-04-30 18:14:51

+0

@RickViscomi同意,因为代码状态var c1 = captcha,c2 = captcha; c1和c2都是指向验证码对象的指针,因此它们都是同一个对象,这会导致更改1个对象c1以影响c2和catcha对象。 – abc123 2013-04-30 18:21:17

+0

啊,这一切都有道理。谢谢!我想我的印象是,定义这些变量会创建一个实例而不是指针。你们中的任何一个人都可以让我知道为什么对象存储在变量中,而不是存储在变量中的数字? 'var myNumber = 1,myNewNumber = myNumber;'** vs **'var myObject = {prop1:'red'},myNewObject = myObject;' – 2013-04-30 18:26:22

回答

0

虽然@plalx有一个有效的答案,但它不是我的方案的理想答案。既然不能实例化是从对象文本(不使用Object.create)创建了一个类,我决定修改我的类与函数:

$(function(){ 
    var Captcha = function(){ 
     var parentForm = '', 
      container = '', 
      captcha_input = '', 
      number1 = 0, 
      number2 = 0, 

      createCaptcha = function(form_ID){ 
       var newHtml; 
       this.parentForm = $('#' + form_ID); 
       this.container = this.parentForm.find('.captchaContainer'); 
       this.number1 = randomNumber(10); 
       this.number2 = randomNumber(10); 


       newHtml = 'What does ' + this.number1 + ' plus ' + this.number2 + ' equal? <b class="required goldenrod" title="Required Field">*</b><br/><br/><input type="text" name="captcha">'; 
       this.container.html(newHtml); 
      }, 

      isValid = function(){ 
       this.captcha_input = this.container.find('input[name="captcha"]'); 
       if (this.number1 + this.number2 == this.captcha_input.val()) { 
        this.captcha_input.css('background-color', '') 
        return true; 
       } else{ 
        this.captcha_input.css('background-color', '#FFCCCC') 
        alert(this.number1 + ' plus ' + this.number2 + ' does not equal ' + this.captcha_input.val() + '. Please try again.'); 
        this.captcha_input.focus(); 
        return false; 
       } 
      }, 

      randomNumber = function(max){ return Math.floor(Math.random()*(max+1)); } 

      return{ 
       createCaptcha : createCaptcha, 
       isValid : isValid 
      } 
    } 


    // Instantiation of Captcha objects 
    var c1 = new Captcha, 
     c2 = new Captcha; 

    c1.createCaptcha("form1"); 
    c2.createCaptcha("form2"); 

    $('#form1 input[type="submit"]').click(function() { if(c1.isValid()){ alert('Captcha is valid!'); }else{ return false; } }); 
    $('#form2 input[type="submit"]').click(function() { if(c2.isValid()){ alert('Captcha is valid!'); }else{ return false; } }); 

}); 

这是新的工作fiddle

TLDR:由于对象文字离不开Object.create被实例化,我用一个函数来创建类,而不是,然后实例化,像这样:

var c1 = new Captcha, 
    c2 = new Captcha; 
+1

'var c1 = $ .extend({},captcha)'等等也会起作用。 – numbers1311407 2013-04-30 20:52:45

+0

有趣。不是一个不好的解决方案, – 2013-04-30 20:55:19

1

c1c2都是同一个对象。使用Object.create来创建不同的实例。旧版浏览器不支持Object.create,但是我提供的链接中有一个填充。

var c1 = Object.create(captcha), 
    c2 = Object.create(captcha); 
+0

看起来像这样会为我做伎俩。我想我只是误解了如何实例化一个由对象文字组成的类。在我接受这个答案之前,你知道'Object.create'是否存在任何跨浏览器问题吗? – 2013-04-30 18:29:57

+0

@FillipPeyton是的,使用[polyfill](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create#Polyfill)来支持不兼容的浏览器。 – bfavaretto 2013-04-30 18:34:20

+0

@bfavaretto - 谢谢你。虽然这个polyfill可以解决我的问题,但我不一定要添加更多的代码,因为我只能重构我的类,以便从函数而不是对象文本创建。如果你想提交一个建议使用函数的答案,我会很乐意接受这个答案。谢谢! – 2013-04-30 18:44:26

1

您还可以执行对象的深层副本。

function deepCopy(obj) { 
    var res = {}; 
    for (var key in obj) { 
     if (obj.hasOwnProperty(key)) { 
      res[key] = obj[key]; 
     }; 
    } 
    res.prototype = obj.prototype; // this would make it a deep copy. 
    return res; 
}; 
var c1 = deepCopy(captcha); 
+0

有趣的。从来不知道这一点。谢谢@ alex23! – 2013-04-30 20:49:34

+0

这将适用于这种情况,但它不是深层复制。 – numbers1311407 2013-04-30 20:57:04

相关问题