CPF generator in Javascript

Asked

Viewed 3,485 times

6

I made a CPF generator in Javascript and, I wanted to know if my code is good or what I can improve on it?

Function that will be called by the event onsubmit

function gerarCpf() {
var cpf = document.getElementById("cpf");

var num1 = aleatorio().toString();
var num2 = aleatorio().toString();
var num3 = aleatorio().toString();

var dig1 = digPri(num1,num2,num3);
var dig2 = digSeg(num1,num2,num3,dig1);
cpf.value = num1+"."+num2+"."+num3+"-"+dig1+""+dig2;}

Function Calculating First Digit Checker

function digPri(n1,n2,n3) {
var nn1 = n1.split("");
var nn2 = n2.split("");
var nn3 = n3.split("");
var nums = nn1.concat(nn2,nn3);

var x = 0;
var j = 0;
for (var i=10;i>=2;i--) {
    x += parseInt(nums[j++]) * i;
}
var y = x % 11;
if (y < 2) {
    return 0;
} else {
    return 11-y;
}}

Function Calculating Second Digit Checker

function digSeg(n1,n2,n3,n4) {
var nn1 = n1.split("");
var nn2 = n2.split("");
var nn3 = n3.split("");
var nums = nn1.concat(nn2,nn3);
nums[9] = n4;
var x = 0;
var j = 0;
for (var i=11;i>=2;i--) {
    x += parseInt(nums[j++]) * i;
}
var y = x % 11;
if (y < 2) {
    return 0;
} else {
    return 11-y;
}}

Function that returns random number with 3 fixed digits

function aleatorio() {
var aleat = Math.floor(Math.random() * 999);
if (aleat < 100) {
    if (aleat < 10) {
        return "00"+aleat;
    } else {
        return "0"+aleat;
    }
} else {
    return aleat;
}}
  • 2

    I recommend indenting better....

1 answer

9


The biggest improvement to be made in your code is to transform the two functions of generating the check digits into one, since they are almost equal.

It also has several other details of both writing and structuring that can improve.

Could stay like this:

//obtem o elemento apenas uma vez no inicio em vez de todas as vezes que gera o cpf
const cpf = document.getElementById("cpf"); 

function gerarCpf() {
  const num1 = aleatorio(); //aleatorio já devolve string, logo não precisa de toString
  const num2 = aleatorio();
  const num3 = aleatorio();

  const dig1 = dig(num1, num2, num3); //agora só uma função dig
  const dig2 = dig(num1, num2, num3, dig1); //mesma função dig aqui

  //aqui com interpolação de strings fica bem mais legivel
  return `${num1}.${num2}.${num3}-${dig1}${dig2}`;
}

//o quarto parametro(n4) só será recebido para o segundo digito
function dig(n1, n2, n3, n4) { 
  
  //as concatenações todas juntas uma vez que são curtas e legíveis
  const nums = n1.split("").concat(n2.split(""), n3.split(""));
  
  if (n4 !== undefined){ //se for o segundo digito coloca o n4 no sitio certo
    nums[9] = n4;
  }
  
  let x = 0;
   
  //o j é também iniciado e incrementado no for para aproveitar a própria sintaxe dele
  //o i tem inicios diferentes consoante é 1º ou 2º digito verificador
  for (let i = (n4 !== undefined ? 11:10), j = 0; i >= 2; i--, j++) {
    x += parseInt(nums[j]) * i;
  }
  
  const y = x % 11;
  //ternário aqui pois ambos os retornos são simples e continua legivel
  return y < 2 ? 0 : 11 - y; 
}

function aleatorio() {
  const aleat = Math.floor(Math.random() * 999);
 //o preenchimento dos zeros à esquerda é mais facil com a função padStart da string
  return ("" + aleat).padStart(3, '0'); 
}

cpf.value = gerarCpf();
<input type="text" id="cpf">

Note also that I have chosen to turn all statements into let or const which are the most modern and correct ways to do today.

No comment

Follow the same code without comments to be able to copy from here and use without having the explanations in text:

const cpf = document.getElementById("cpf"); 

function gerarCpf() {
  const num1 = aleatorio();
  const num2 = aleatorio();
  const num3 = aleatorio();
  const dig1 = dig(num1, num2, num3);
  const dig2 = dig(num1, num2, num3, dig1);
  return `${num1}.${num2}.${num3}-${dig1}${dig2}`;
}

function dig(n1, n2, n3, n4) { 
  const nums = n1.split("").concat(n2.split(""), n3.split(""));
  if (n4 !== undefined){ 
    nums[9] = n4;
  }
  
  let x = 0;
  for (let i = (n4 !== undefined ? 11:10), j = 0; i >= 2; i--, j++) {
    x += parseInt(nums[j]) * i;
  }
  
  const y = x % 11;
  return y < 2 ? 0 : 11 - y; 
}

function aleatorio() {
  const aleat = Math.floor(Math.random() * 999);
  return ("" + aleat).padStart(3, '0'); 
}

cpf.value = gerarCpf();
<input type="text" id="cpf">

Code Golf

In the name of curiosity and grace, and in an attempt to do a little Code Golf in its code to make it super short at the writing level (although not very readable) could do so:

function gerarCpf() {
  const n1 = aleatorio(), n2 = aleatorio(), n3 = aleatorio(), d1 = dig(n1, n2, n3);
  return `${n1}.${n2}.${n3}-${d1}${dig(n1, n2, n3, d1)}`;
}

function dig(n1, n2, n3, n4) { 
  let nums = n1.split("").concat(n2.split(""), n3.split(""), [n4]), x = 0;  
  for (let i = (n4 !== undefined ? 11:10), j = 0; i >= 2; i--, j++) x += +nums[j] * i;
  return (y = x % 11) < 2 ? 0 : 11 - (y = x % 11); 
}

const aleatorio = () => ("" + Math.floor(Math.random() * 999)).padStart(3, '0');

document.getElementById("cpf").value = gerarCpf();
<input type="text" id="cpf">

  • Declare as Let and const has some impact on performance or is only aesthetic?

  • 1

    In relation to const helps validate when we are changing something that was not supposed to, as well as opens up more possibilities of optimizing the code itself. As for the let may have implications as regards closures and be slightly slower than var depending on the codes, but ultimately ensures scope by avoiding other types of problems. Overall any performance gains/losses to const and let are minimal and have no real impact on other applications.

  • 1

    @Filipericardo As a curiosity, I found a jsperf that compares var, let and const in performance. See here. In my machine the differences were in the order of 2-4%.

  • Speaks professor Isac! sometimes this code generates a invalid Cpf, like this: 904.384.710-00. as I noticed that the invalids usually have 00 at the end

  • 1

    @Juliohenrique This code ended up only improving what was in the question at the level of code and readability but maintaining logic. I’ll take a look at the CPF rules to see if I see the problem and I’ll be back to say something.

  • 1

    @Juliohenrique Actually it had been a bug that I had introduced in refactoring, which affected only when the CPF had the first checker type as 0. At this point it was solved. Thank you for the comment.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.