=== vs includes

Benchmark created on


Setup

const tests = [...`const $v1 = (() => {
  const elementCache = new WeakMap()
  const create = ({ tag, attrs = {}, events = {}, children = [] } = {}) => {
    if (!tag) {
      throw Error('Cannot create element without a tag name!')
    }
    const element = document.createElement(tag)
    Object.entries(attrs).forEach(([key, value]) => {
      if (element[key] !== undefined) {
        element[key] = value
      } else {
        element.setAttribute(key, value)
      }
    })
    Object.entries(events).forEach(([key, value]) => element.addEventListener(key, value))
    children.forEach(child => element.append(create(child)))
    elementCache.set(element, { events })
    return element
  }
  const query = (...selectors) => {
    return selectors.map(selector => {
      return !Array.isArray(selector)
        ? document.querySelector(selector)
        : selector.flatMap(s => document.querySelectorAll(s))
    })
  }
  const append = (parent, child) => {
    if (!parent) {
      throw Error('Cannot append to a null/undefined parent!')
    }
    if (Array.isArray(child)) {
      return child.map(c => append(parent, c))
    } else {
      if (!(child instanceof HTMLElement)) {
        child = create(child)
      }
      parent.appendChild(child)
      return child
    }
  }
  const destroy = (element) => {
    if (!element || !(element instanceof HTMLElement)) { return } if (element.children) { Array.from(element.children).forEach(child => destroy(child)) } if (elementCache.has(element)) { const { events } = elementCache.get(element); Object.entries(events).forEach(([key, value]) => element.removeEventListener(key, value)) } element.remove()
  }
  return { query, create, append, destroy }
})()

const tokenizer = expr => {
  const escaped = {
    'n': '\n',
    't': '\t',
    'r': '\r',
    'f': '\f',
    'v': '\v',
    'b': '\b',
    '0': '\0',
    'a': '\a'
  }
  const doubleOperators = {
    '=': '===',
    '!': '!==',
    '&': '&&',
    '|': '||',
    '<': '<=',
    '>': '>=',
    '+': '++',
    '-': '--',
  }
  const tokens = []
  let i = 0
  while (i < expr.length) {
    let c = expr[i]
    if (c === '0' || c === '1' || c === '2' || c === '3' || c === '4' || c === '5' || c === '6' || c === '7' || c === '8' || c === '9') {
      let value = ''
      let prePeriod = true
      while (prePeriod && /[0-9.]/.test(c) || !prePeriod && /[0-9]/.test(c)) {
        if (c === '.') {
          prePeriod = false
        }
        value += c
        c = expr[++i]
      }
      tokens.push({ type: 'number', value })
    } else if (/[+\-/*()^?:!<>=&|]/.test(c)) {
      if ()
    } else if (/["']/.test(c)) {
      const quote = c
      let value = ''
      c = expr[++i]
      while (c !== quote) {
        if (c === '\\' && (expr[i + 1] === quote || expr[i + 1] === '\\')) {
          value += quote
          i++
        } else if (c === '\\') {
          const next = expr[i + 1]
          if (escaped[next]) {
            value += escaped[next]
            i++
          } else {
            value += c
            i++
          }
        } else {
          value += c
          c = expr[++i]
        }
      }
      tokens.push({ type: 'string', value })
    } else if (/[a-zA-Z_]/.test(c)) {
      let value = ''
      while (/[a-zA-Z0-9_]/.test(c)) {
        value += c
        c = expr[++i]
      }
      tokens.push({ type: 'identifier', value })
    } else if (c === ' ') {
      i++
    }
  }
  return tokens
}
`]

Test runner

Ready to run.

Testing in
TestOps/sec
===
tests.forEach(c => console.log(c === '0' || c === '1' || c === '2' || c === '3' || c === '4' || c === '5' || c === '6' || c === '7' || c === '8' || c === '9'))
ready
includes
const digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
tests.forEach(c => console.log(digits.includes(c)))
ready
regex
tests.forEach(c => console.log(/0-9/.test(c)))
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.