2013-04-30 53 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

相關問題