插入Boolean类型的节点
Boolean
在js中是一个基础类型,没有什么特别需要注意的地方,在我们日常的开发工作中,我们一般会有以下几种方法声明一个Boolean
类型的变量。
字面量声明
javascriptvar bool1 = false
使用
new
关键字javascriptvar bool2 = new Boolean(false)
使用拆箱转换
javascriptvar bool3 = !!1
这些方法都是日常工作中使用的比较多的方法,下面就是我们使用types
创建Boolean
类型节点的方法。
使用字面量
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中的全部的基础类型:
类型 使用函数 NumericLiteral t.numericLiteral(value) StringLiteral t.stringLiteral(value) BooleanLiteral t.booleanLiteral(value) NullLiteral t.nullLiteral() Identifier t.identifier(name) 使用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
。使用拆箱转换
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 对表达式求值并返回 undefined
t.unaryExpression delete 删除对象的属性 t.unaryExpression await 等待一个 Promise 对象的解决,只能用于异步函数中 t.awaitExpression yield 将生成器函数的执行暂停,并返回一个值 t.yieldExpression
在这里回到主题,可以看上表,没有针对!!
双逻辑非的表达式,但是我们可以将它看做两个逻辑非组合在一起。所以我们可以在例3中看到我们是怎么实现的双非逻辑符。
对于自加/自减运算符,我们可以直接使用types
提供的updateExpression
表达式实现其逻辑。这里我们必须将其区分开++/--
与!!
是两回事,在js中没有对!!
的定义,它本身就是一个组合表达式。
除了await
与yield
语句,这两个语句我们将在Functoin
中出现具体的例子,其他的单目运算符都已经出现在下面的例子当中了。
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中我们Object
与Function
是最复杂的两块内容,里面东西最多,有继承链、原型链、闭包和异步函数,只要我们掌握了这些内容,就可以直接说精通js啦。
源码地址: