'What's the best way to mask a credit card in JavaScript?

In Node, I need to turn a credit card into something like this before rendering the view layer: ************1234.

Without loops and ugliness is there a utility or one liner for this? The credit card can potentially look one of these ways:

1234567898765432
1234-5678-9876-5432
1234 5678 9876 5432


Solution 1:[1]

Here's one way with Ramda and some RegEx:

var ensureOnlyNumbers  = R.replace(/[^0-9]+/g, '');
var maskAllButLastFour = R.replace(/[0-9](?=([0-9]{4}))/g, '*');
var hashedCardNumber   = R.compose(maskAllButLastFour, ensureOnlyNumbers);

hashedCardNumber('1234567898765432'); // ************5432

Demo : http://jsfiddle.net/7odv6kfk/

Solution 2:[2]

No need for a regex:

var cc='1234-5678-9012-3456';
var masked = '************'+cc.substr(-4); // ************3456

Will work for any format provided the last four digits are contiguous.

Solution 3:[3]

This is for everyone who said they didn't need another way to mask a credit card. This solution will append the last 4 chars of the card number with asterisk.

var cardNumber       = '4761640026883566';
console.log(maskCard(cardNumber));

function maskCard(num) {
  return `${'*'.repeat(num.length - 4)}${cardNumber.substr(num.length - 4)}`;
}

jsfiddle example

Solution 4:[4]

Here's plain JavaScript using Regex with lookahead

var cardNumbers = [
  "1234567898765432",
  "1234-5678-9876-5432",
  "1234 5678 9876 5432"
];

console.log(cardNumbers.map(maskCardNumber));
//> ["************5432", "************5432", "************5432"]

function maskCardNumber(cardNumber) {
  return cardNumber.replace(/^[\d-\s]+(?=\d{4})/, "************");
};

Unlike AllienWebguy's implementation:

  • doesn't require an external library
  • does everything in one replace() call
  • replaces whatever number of digits with the constant number of asterisks (it should be a bit faster, but it may not be what you want)
  • supports only described formats (will not work, for example, with "1B2C3D4E5F6G7H89876-5432" or "1234+5678+9876=54-32")

Solution 5:[5]

Remove non digits, generate an asterisk string of that length - 4, append the last 4:

var masked = Array(cc.replace(/[^\d]/g, "").length - 3).join("*") + cc.substr(cc.length - 4);

Or to include space/hyphens in the mask:

var masked = Array(cc.length - 3).join("*") + cc.substr(cc.length - 4);

Solution 6:[6]

I use this function that is useful for me, because mask the credit card number and format it in blocks of four characters like this **** **** **** 1234, here the solution:

const maskCreditCard = (card) => {
  return card
    .replace(/.(?=.{5})/g, "*")
    .match(/.{1,4}/g)
    .join(" ");
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AlienWebguy
Solution 2
Solution 3 jjbskir
Solution 4
Solution 5 Alex K.
Solution 6 Jose Alvarez