You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript信用卡验证:循环遍历表单字段遇报错求解决方案

Let's break down your issues step by step, fix the immediate errors, and then share a cleaner, more robust implementation that meets all your credit card validation requirements—including the extra credit for returning a validation status object.


First, Fix the Immediate Errors

Your two main errors come from simple typos, missing elements, and incorrect logic:

1. Uncaught TypeError: Cannot read property '1' of undefined & Cannot read property 'style' of null

Let's tackle the root causes:

  • Duplicate ID in HTML: Your last input field has id="creditCard3" instead of id="creditCard6"—so when your loop reaches i=6, document.getElementById("creditCard6") returns null, breaking the code. Fix that line in your HTML:
    <label for="creditCard6">Card Number</label>
    <input type="text" name="creditCard6" id="creditCard6" placeholder="XXXX-XXXX-YYYY-AAAA" onChange="validateCreditCard()" /><br />
    
  • Typo in JS: In the else block, you wrote document.getElementById("cardCard" + i)—that's a typo, should be creditCard instead of cardCard.
  • Missing "message" element: Your HTML doesn't have an element with id="message", so document.getElementById("message") returns null. You'll need to add this (or better, add per-input error messages for clarity).
  • Testing the DOM element instead of its value: pattern.test(cardNumber) is testing the input element object, not its actual value. You need to use cardNumber.value instead.

2. Incomplete Validation Logic

Your current regex only checks the format and last digit evenness, but misses critical requirements:

  • At least two different digits
  • Sum of all digits > 16
  • Ensuring the total number of digits (after removing hyphens) is exactly 16

Better Implementation (Meets All Requirements + Extra Credit)

Let's refactor this to be more maintainable, user-friendly, and fully compliant with your rules. We'll add real-time validation, per-input error messages, and a reusable validation function that returns a status object.

Updated HTML

We'll use a class for input fields, add dedicated error containers for each input, and use the input event for instant validation:

<!DOCTYPE html>
<html>
<head>
    <title>Credit Card Validation</title>
    <!--Lisa Hergert's Extra Credit 1-->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="extraCredit.js"></script>
    <style>
        .credit-card-input { margin-bottom: 5px; }
        .valid { color: green; border: 1px solid green; }
        .error { color: red; border: 1px solid red; }
        .error-message { font-size: 0.8em; color: red; margin-bottom: 12px; }
    </style>
</head>
<body>
    <form name="newForm">
        <!-- Card Input 1 -->
        <div>
            <label for="creditCard1">Card Number</label>
            <input type="text" name="creditCard1" id="creditCard1" class="credit-card-input" placeholder="XXXX-XXXX-YYYY-AAAA" />
            <div id="error-creditCard1" class="error-message"></div>
        </div>
        <!-- Card Input 2 -->
        <div>
            <label for="creditCard2">Card Number</label>
            <input type="text" name="creditCard2" id="creditCard2" class="credit-card-input" placeholder="XXXX-XXXX-YYYY-AAAA" />
            <div id="error-creditCard2" class="error-message"></div>
        </div>
        <!-- Card Input 3 -->
        <div>
            <label for="creditCard3">Card Number</label>
            <input type="text" name="creditCard3" id="creditCard3" class="credit-card-input" placeholder="XXXX-XXXX-YYYY-AAAA" />
            <div id="error-creditCard3" class="error-message"></div>
        </div>
        <!-- Card Input 4 -->
        <div>
            <label for="creditCard4">Card Number</label>
            <input type="text" name="creditCard4" id="creditCard4" class="credit-card-input" placeholder="XXXX-XXXX-YYYY-AAAA" />
            <div id="error-creditCard4" class="error-message"></div>
        </div>
        <!-- Card Input 5 -->
        <div>
            <label for="creditCard5">Card Number</label>
            <input type="text" name="creditCard5" id="creditCard5" class="credit-card-input" placeholder="XXXX-XXXX-YYYY-AAAA" />
            <div id="error-creditCard5" class="error-message"></div>
        </div>
        <!-- Card Input 6 -->
        <div>
            <label for="creditCard6">Card Number</label>
            <input type="text" name="creditCard6" id="creditCard6" class="credit-card-input" placeholder="XXXX-XXXX-YYYY-AAAA" />
            <div id="error-creditCard6" class="error-message"></div>
        </div>
    </form>
</body>
</html>

Updated JavaScript

We'll create a standalone validation function that returns an object with isValid and errors, then wire up real-time validation for all inputs:

// Wait for the DOM to fully load before attaching events
document.addEventListener('DOMContentLoaded', function() {
    // Get all credit card input fields
    const cardInputs = document.querySelectorAll('.credit-card-input');
    
    // Attach real-time validation to each input
    cardInputs.forEach(input => {
        input.addEventListener('input', function() {
            validateSingleCard(this);
        });
    });
});

/**
 * Validates a credit card number against all required rules
 * @param {string} cardNumber - The raw input value (with hyphens allowed)
 * @returns {Object} - Validation result: { isValid: boolean, errors: string[] }
 */
function validateCreditCardNumber(cardNumber) {
    const errors = [];
    // Clean the input by removing hyphens
    const cleanDigits = cardNumber.replace(/-/g, '');

    // Rule 1: Must be exactly 16 digits (after removing hyphens)
    if (cleanDigits.length !== 16) {
        errors.push('Must be exactly 16 digits (hyphens are allowed for formatting)');
    }

    // Rule 2: Must only contain digits (and hyphens)
    if (!/^[\d-]+$/.test(cardNumber) || !/^\d{16}$/.test(cleanDigits)) {
        errors.push('Can only contain digits and hyphens');
    }

    // Rule 3: Last digit must be even
    const lastDigit = parseInt(cleanDigits[15], 10);
    if (lastDigit % 2 !== 0) {
        errors.push('Last digit must be even');
    }

    // Rule 4: At least two different digits
    const uniqueDigits = new Set(cleanDigits);
    if (uniqueDigits.size < 2) {
        errors.push('Must contain at least two different digits');
    }

    // Rule 5: Sum of all digits is greater than 16
    const digitSum = cleanDigits.split('').reduce((sum, digit) => sum + parseInt(digit, 10), 0);
    if (digitSum <= 16) {
        errors.push(`Sum of digits (${digitSum}) must be greater than 16`);
    }

    return {
        isValid: errors.length === 0,
        errors: errors
    };
}

/**
 * Handles UI updates for a single input's validation result
 * @param {HTMLElement} inputElement - The input field to validate
 * @returns {Object} - The validation result object (for extra credit)
 */
function validateSingleCard(inputElement) {
    const validationResult = validateCreditCardNumber(inputElement.value);
    const errorElement = document.getElementById(`error-${inputElement.id}`);

    // Update input styling and error messages
    if (validationResult.isValid) {
        inputElement.classList.remove('error');
        inputElement.classList.add('valid');
        errorElement.textContent = '';
    } else {
        inputElement.classList.remove('valid');
        inputElement.classList.add('error');
        errorElement.textContent = validationResult.errors.join('\n');
    }

    // Return the result for extra credit use cases
    return validationResult;
}

Key Improvements

  • Real-time validation: Uses the input event instead of onChange so users get feedback immediately as they type.
  • Reusable logic: Separates validation logic from UI updates, making it easy to test or reuse the validation function elsewhere.
  • Clear error feedback: Each input has its own error message, so users know exactly what's wrong with their entry.
  • Meets all requirements: Fully covers all your validation rules, plus returns a structured validation object as requested for extra credit.
  • Robust DOM handling: Uses DOMContentLoaded to ensure elements exist before attaching events, eliminating null reference errors.

内容的提问来源于stack exchange,提问作者Lisa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:25:33