Skip to content

插入Boolean类型的节点

Boolean在js中是一个基础类型,没有什么特别需要注意的地方,在我们日常的开发工作中,我们一般会有以下几种方法声明一个Boolean类型的变量。

  1. 字面量声明

    javascript
    var bool1 = false
  2. 使用new关键字

    javascript
    var bool2 = new Boolean(false)
  3. 使用拆箱转换

    javascript
    var bool3 = !!1

这些方法都是日常工作中使用的比较多的方法,下面就是我们使用types创建Boolean类型节点的方法。

  1. 使用字面量

    javascript
    /**
       * @NOTE 声明一个值为false的变量bool1
       * var bool1 = false
       */
      const bool1 = t.variableDeclaration('const', [
        t.variableDeclarator(t.identifier('bool1'), t.booleanLiteral(false))
      ])

    这一段我们需要认识一个新的函数booleanLiternal,用于新增一个Boolean类型的字面量。对于基础类型,从Number类型开始,我们就大致上发现了一个规律,每一个基础数据类型,types都会准备一个单独的字面量函数,用于创建对应的基础类型值。

    到目前为止,我们已经认识到了以下几种声明字面量的函数,已经覆盖了JS中的全部的基础类型:

    类型使用函数
    NumericLiteralt.numericLiteral(value)
    StringLiteralt.stringLiteral(value)
    BooleanLiteralt.booleanLiteral(value)
    NullLiteralt.nullLiteral()
    Identifiert.identifier(name)
  2. 使用new关键字实例化

    javascript
    /**
       * @NOTE 使用new关键字创建
       * var bool2 = new Boolean(false)
       */
      const newNode = t.newExpression(t.identifier('Boolean'), [
        t.booleanLiteral(false)
      ])
      const bool2 = t.variableDeclaration('const', [
        t.variableDeclarator(t.identifier('bool2'), newNode)
      ])

    继续使用我们之前已经使用的过的函数newExpression表达式,和上面提到的声明Boolean字面量的函数booleanLiternal

  3. 使用拆箱转换

    javascript
    /**
       * @NOTE 使用拆箱转换
       * var bool3 = !!1
       */
      const unaryNode = t.unaryExpression('!', t.numericLiteral(1), true)
      const unaryNode1 = t.unaryExpression('!', unaryNode, true)
      const bool3 = t.variableDeclaration('const', [
        t.variableDeclarator(t.identifier('bool3'), unaryNode1)
      ])

    这里我们需要认识一个新函数unaryExpress单目表达式,用于单目运算符。

    运算符描述使用函数
    +对数字类型执行正号操作,对数字字符串类型进行强制类型转换t.unaryExpression
    -对数字类型执行负号操作,对数字字符串类型进行强制类型转换并执行负号操作t.unaryExpression
    !对布尔值进行逻辑非运算,将非布尔值操作数转换成布尔值t.unaryExpression
    ~对 32 位带符号整数执行按位取反操作t.unaryExpression
    ++对变量执行递增操作,前缀形式和后缀形式均可使用t.updateExpression
    --对变量执行递减操作,前缀形式和后缀形式均可使用t.updateExpression
    typeof返回操作数的数据类型t.unaryExpression
    void对表达式求值并返回 undefinedt.unaryExpression
    delete删除对象的属性t.unaryExpression
    await等待一个 Promise 对象的解决,只能用于异步函数中t.awaitExpression
    yield将生成器函数的执行暂停,并返回一个值t.yieldExpression

在这里回到主题,可以看上表,没有针对!!双逻辑非的表达式,但是我们可以将它看做两个逻辑非组合在一起。所以我们可以在例3中看到我们是怎么实现的双非逻辑符。

对于自加/自减运算符,我们可以直接使用types提供的updateExpression表达式实现其逻辑。这里我们必须将其区分开++/--!!是两回事,在js中没有对!!的定义,它本身就是一个组合表达式。

除了awaityield语句,这两个语句我们将在Functoin中出现具体的例子,其他的单目运算符都已经出现在下面的例子当中了。

javascript
import core from '@babel/core'
import fs from 'fs-extra'
import t from '@babel/types'

const filepath = './demo.js'

const workflow = async () => {
  const source = await fs.readFile(filepath, { encoding: 'utf-8' })
  const ast = await core.parse(source, { sourceType: 'module' })

  /**
   * @NOTE 使用 + 运算符
   * 
   * var node1 = +1
   */
  const unaryNode1 = t.variableDeclaration('const', [
    t.variableDeclarator(t.identifier('node1'), t.unaryExpression('+', t.numericLiteral(1), true))
  ])

  /**
   * @NOTE 使用 - 运算符
   * var node2 = -1
   */
  const unaryNode2 = t.variableDeclaration('const', [
    t.variableDeclarator(t.identifier('node2'), t.unaryExpression('-', t.numericLiteral(1), true))
  ])

  /**
   * @NOTE 自增与自减 同理
   * var node3 = ++1
   * var node4 = --1
   */
  const increateNode = t.updateExpression('++', t.numericLiteral(1), true)
  const unaryNode3 = t.variableDeclaration('const', [
    t.variableDeclarator(t.identifier('node3'), increateNode)
  ])

  /**
   * @NOTE 实现取反的逻辑操作符
   * 
   * var node4 = !1
   */
  const unaryNode4 = t.variableDeclaration('const', [
    t.variableDeclarator(t.identifier('node4'), t.unaryExpression('!', t.numericLiteral(1), true))
  ])

  /**
   * @NOTE 派生操作 实现!!
   */
  const node5C = t.unaryExpression('!', t.numericLiteral(1), true)
  const node5 = t.unaryExpression('!', node5C, true)
  const unaryNode5 = t.variableDeclaration('const', [
    t.variableDeclarator(t.identifier('node5'), node5)
  ])

  /**
   * @NOTE 实现typeof
   * typeof 1
   */
  const typeofNode = t.variableDeclaration('const', [
    t.variableDeclarator(t.identifier('typeofNode'), t.unaryExpression('typeof', t.numericLiteral(1), true))
  ])

  /**
   * @NOTE 实现delete 操作符
   * delete obj.name
   */
  const deleteNode = t.unaryExpression('delete', t.memberExpression(t.identifier('obj'), t.identifier('name')))

  ast.program.body.push(unaryNode1, unaryNode2, unaryNode3, unaryNode4, unaryNode5, typeofNode, deleteNode)

  const output = await core.transformFromAstSync(ast)
  console.log('=======> workflow.ast', output.code)
}

workflow()

现在我们已经基本上将基础类型、复杂类型和单目运算符都过了一遍,在这个基础上,我们将继续学习Function类型。在JS中我们ObjectFunction是最复杂的两块内容,里面东西最多,有继承链、原型链、闭包和异步函数,只要我们掌握了这些内容,就可以直接说精通js啦。

源码地址:

  1. babel创建boolean类型: https://github.com/stack-wuh/mini-cli/blob/main/core/create-boolean-babel/babel.js
  2. babel创建单目运算符: https://github.com/stack-wuh/mini-cli/blob/main/core/create-unary-express/babel.js

MIT License.