First of all, you cannot compare arrays like this if (arr[i] + arr[i + 1] === nOpp). In this case, === will compare if both sides of the comparison are Array type objects, and if they are the same object, not if their content is the same, for that you should use other ways.
Open node.js CLI and paste this code
const nOpp = ["N", "S"];
console.log(nOpp === ["N", "S"]);
and you'll see false printed in the console.
For a more detailed explanation, look here: How to compare arrays in JavaScript?
Second, nesting if like this is equivalent to successive ANDs
    if (arr[i] + arr[i + 1] === nOpp) 
    if (arr[i] + arr[i + 1] === sOpp)
    if (arr[i] + arr[i + 1] === eOpp)
    if (arr[i] + arr[i + 1] === wOpp) {
     ...
    }
This means that only if the first if evaluates to true the second one will be evaluated if this evaluates to true the third will be evaluated, and so on.
Now, that all being said, here is my version.
I just took into account the first paragraph of your question, and the desired result, then came to this:
let arr = ["N", "E", "W", "S", "W", "S", "N", "W"]
const opposites = [
  ["N", "S"],
  ["W", "E"],
];
const checkForOpposites = data => {
  const result = [];
  data.forEach((v0, i, a) => {
    let oppositeFound = false;
    opposites.forEach(o => {
      if (v0 != a[i+1] && o.includes(v0) && o.includes(a[i+1])) {
        oppositeFound = true
        result.push(i, i+1);
      }
    });
//     console.log(`${i} => ${v0} | ${i+1} => ${a[i+1]} | ${oppositeFound}`);
  });
  return result;
}
const cleanOpposites = data => {
  let result = data;
  let n = [];
  do {
    n = checkForOpposites(result);
//     console.log(n);
    if (n.length > 0) {
      result = result.reduce((accum, curr, i) => {
        if (!n.includes(i)) {
          accum.push(curr);
        }
        return accum;
      }, []);
    }
//     console.log(result);
  } while (n.length > 0);
  
  return result;
}
const r0 = cleanOpposites(arr);
console.log(arr);
console.log(r0);
The cleaning process should be recursive due to this:
In the first iteraction we get this result:
indexes of items deleted: [1, 2, 5, 6]
resulting array: ["N", "S", "W", "W"]
But there remains ["N", "S",... that shouldn't be part of the final result, so to achieve your requirement, I think we must iterate through the checkForOpposites function till it returns no matches.
Certainly, the code can be shortened, but this would give you an idea of how to do it.