O ponto chave aqui é, antes de qualquer coisa, obter apenas os parêntesis, colchetes e chaves de dentro da string. Depois disso precisamos pensar em uma forma de encontrar cada par correspondente (abertura e fechamento) desses parêntesis, colchetes e chaves. Uma forma possível de fazer isso é, a cada par válido encontrado, a nossa função remover o par válido, assim a nossa string eventualmente terá apenas os parêntesis, colchetes ou chaves sem par, sendo inválida, ou então estará sem nenhum deles, o que significa que é válida.
Mais uma vez podemos usar as expressões regulares em nosso favor para simplificar o nosso trabalho. O primeiro passo para resolver o problema é encontrar uma forma de obter apenas os parêntesis, colchetes e chaves da string, se livrando de todo o resto que não importa. Uma RegEx com o método .match() não server apenas para encontrar ocorrências, mas também para retornar essas ocorrências, e elas são retornadas em formato de array. Portanto podemos utilizá-las em conjunto com um .join() para obter os parêntesis, colchetes e chaves e unir tudo em uma string. Note que precisar escapar, através de uma \, os caracteres que são especiais para as RegEx.
function bracketCheck(str) { let brackets = str.match(/\\(|\\)|\\[|\\]|\\{|\\}/g).join('')
}
Após conseguir separar os parêntesis podemos começar a removê-los da string a cada par válido. Para conseguir isso podemos criar uma repetição WHILE que funcione enquanto nossa string possuir pares válidos de (), [] ou {}, ou seja, enquanto ele conseguir encontrar pares válidos esses pares vão sendo removidos um a um. Dentro da repetição, para remover os pares válidos podemos utilizar um outro método em conjunto com as RegEx, o .replace(). Esse método serve para substituir o conteúdo obtido com a RegEx por outro qualquer, que no nosso caso será nada, ou seja, aspas vazias. Com isso conseguiremos remover todos os pares válidos possíveis de dentro da string, e sobrarão apenas parêntesis, colchetes ou chaves inválidos, ou então uma string vazia. Por fim, vamos retornar true ou false baseado em uma verificação do tamanho da string, afinal, se ela estiver vazia será uma string válida mas se não estiver será inválida.
function bracketCheck(str) {
let brackets = str.match(/\\(|\\)|\\[|\\]|\\{|\\}/g).join('')
while (brackets.match(/\\(\\)|\\[\\]|\\{\\}/)) {
brackets = brackets.replace(/\\(\\)|\\[\\]|\\{\\}/, '')
console.log(brackets)
}
return brackets.length === 0
}