【问题标题】:Why is this javascript object referring to a previous object's properties?为什么这个 javascript 对象引用了前一个对象的属性?
【发布时间】:2013-04-30 18:12:17
【问题描述】:

我正在创建一个可以在页面上创建任意数量的验证码的类。我有一个captcha 类,用于实例化新的验证码对象c1c2。这是我的 JS:

 $(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 的提交按钮时,似乎正在为c2 运行isValid 方法,而不是像我预期的那样为c1 运行。知道为什么会这样吗?

需要注意的几点:

  • 如果我添加更多 captcha 实例和 HTML,每个提交按钮将在单击时在 captcha 的最后一个实例上运行 isValid
  • 这需要适用于 IE8+

这是代码的fiddle

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

【问题讨论】:

  • c1 和 c2 都是对同一个 captcha 对象的引用。
  • @RickViscomi 同意,因为代码状态 var c1 = captcha, c2 = captcha; c1 和 c2 都是指向验证码对象的指针,因此它们都是同一个对象,这会导致对 1 个对象 c1 的更改影响 c2 和 catcha 对象。
  • 啊,这一切都说得通。谢谢!我想我的印象是定义这些变量会创建一个实例而不是一个指针。你们中的任何一个都可以告诉我为什么存储在变量中的对象而不是存储在变量中的数字之类的东西会这样吗? var myNumber = 1, myNewNumber = myNumber; vs var myObject = {prop1:'red'}, myNewObject = myObject;
  • @Fillip:它适用于所有数据类型!不同之处在于,在对象的情况下,变量的值是对对象的引用,而不是对象本身。此外,对象是可变的,而数字则不是。
  • @FelixKling - 感谢您的解释!有道理!

标签: javascript jquery class object


【解决方案1】:

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

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

【讨论】:

  • 看起来这对我有用。我想我只是误解了如何实例化由对象文字构成的类。在我接受这个答案之前,您知道Object.create是否存在跨浏览器问题?
  • @FillipPeyton 是的,使用a polyfill 来支持不兼容的浏览器。
  • @bfavaretto - 谢谢。虽然这个 polyfill 可以解决我的问题,但当我可以重构我的类以从函数而不是对象文字创建时,我不一定想添加更多代码。如果您想提交一个建议使用函数的答案,我很乐意接受该答案。谢谢!
  • @FillipPeyton 谢谢,但我可能不会添加另一个答案。如果你决定重新考虑,那个 polyfill 非常简单,而且 Object.create 是当前语言标准的一部分(IE8 及更低版本的旧浏览器不支持它)。
  • @bfavaretto - 很公平。感谢您的帮助!
【解决方案2】:

您还可以执行对象的深层复制。

 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);

【讨论】:

  • 有趣。从来不知道那件事。谢谢@alex23!
【解决方案3】:

虽然@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;

【讨论】:

  • var c1 = $.extend({}, captcha) 等也可以。
  • 有趣。也不错的解决方案,
猜你喜欢
  • 1970-01-01
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-04
  • 1970-01-01
  • 2011-03-11
  • 2014-04-04
相关资源
最近更新 更多