表达式编译的方法写好了,接下来就是如何使编写的代码被我们的翻译机翻译,也就是需要一个容器,两种方法:一种就是类构造器重新定义方法属性,另一种就是将代码作为参数传入我们自定义的方法。接下来介绍一下类构造器中重新定义方法:
export default class OOkay { constructor () { let protos = Object.getOwnPropertyNames(Object.getPrototypeOf(this)) protos.forEach((proto, key, own) => { if(proto != 'constructor'){ Object.defineProperty(this, proto, { value:new Function(translate_block(proto, this[proto].toString())).call(this) }) } }) } }
由上面可以看出,我们使用Object.defineProperty在构造器中重新定义了,translate_block是对整个代码块分割得到进行翻译,代码如下:
/** * 类代码块转换工具 * @param name * @param block * @returns {string} */ export function translate_block (name , block) { let codes = block.split('\n') let reg = new RegExp('^' + name + '$') console.log(reg.source) codes[0] = codes[0].replace(name,'function') for(let i = 1; i < codes.length; i++) { if (codes[i].indexOf('//') != -1) { codes[i] = codes[i].substring(0,codes[i].indexOf('//')) } if(/\*\*|\+|-|\*|\/|%|\.\/|\.\*/g.test(codes[i])){ if (codes[i].indexOf('return ') != -1) { let ret_index = codes[i].indexOf('return ') + 7 codes[i] = codes[i].substring(0,ret_index) + translate(codes[i].substring(ret_index)) }else { let eq_index = codes[i].indexOf('=') + 1 codes[i] = codes[i].substring(0,eq_index) + translate(codes[i].substring(eq_index)) } } } return 'return ' + codes.join('\n') }
对于新的类,我们只要继承OOkay类就可以在该类中使用运算符重载。对于继承自非OOkay类的,我们可以采用注入的方式,如下:
/** * 非继承类的注入方法 * @param target */ static inject (target) { let protos = Object.getOwnPropertyNames(Object.getPrototypeOf(target)) protos.forEach((proto, key, own) => { if (proto != 'constructor') { Object.defineProperty(target, proto, { value:new Function(translate_block(proto, target[proto].toString())).call(target) }) } }) }
对于非类中的代码,我们需要一个容器,这里我采用了两种方式,一种以ookay脚本的方式使用,像这样
<script type='text/ookayscript'>
let a = a+b // a、b为对象实例
</script>
还有就是将代码作为参数传入__$$__方法,该方法编译代码并执行,如下:
static __$__(fn) { if(!(fn instanceof Function)){ throw '参数错误' } (new Function(translate_block('function',fn.toString()))).call(window)() }
这样就实现了运算符的重载
您可能感兴趣的文章: