如何在JavaScript中无需自定义辅助函数即可将构造函数当作普通函数传入参数?
如何在JavaScript中无需自定义辅助函数即可将构造函数当作普通函数传入参数?
我完全懂你遇到的这个问题——用Lodash FP的组合来简化ANTLR4的链式实例化时,构造函数不能直接丢给compose,因为它需要new来调用,直接传的话就会报那个“不能不用new调用构造函数”的错。
你之前尝试直接传构造函数或者硬写new都不行,其实不用自定义_.construct辅助函数,用JavaScript内置的箭头函数或者Reflect.construct就能解决,而且写法也很简洁:
方法1:用箭头函数包裹构造函数调用
直接在_.compose的数组里,给每个构造函数套一层箭头函数,让它接收上一步的结果并通过new实例化:
// imports... import _ from "lodash/fp.js"; const parse = _.compose([ _.invoke("MyQuery"), (tokens) => new MyGrammarParser(tokens), (lexer) => new antlr4.CommonTokenStream(lexer), (chars) => new MyGrammarLexer(chars), (input) => new antlr4.InputStream(input), ]); // 调用测试 const tree = parse("field = 123 AND items in (1,2,3)");
方法2:用Reflect.construct(内置API)
如果你更倾向于用原生API来实例化类,Reflect.construct是专门用来调用构造函数的方法,它和new的效果完全等价,写法如下:
// imports... import _ from "lodash/fp.js"; const parse = _.compose([ _.invoke("MyQuery"), (tokens) => Reflect.construct(MyGrammarParser, [tokens]), (lexer) => Reflect.construct(antlr4.CommonTokenStream, [lexer]), (chars) => Reflect.construct(MyGrammarLexer, [chars]), (input) => Reflect.construct(antlr4.InputStream, [input]), ]);
为什么之前的写法会报错?
- 直接传构造函数(比如
antlr4.InputStream):Lodash FP会把它当作普通函数直接调用(antlr4.InputStream(input)),但构造函数必须用new,所以触发TypeError。 - 直接在
compose里写new antlr4.InputStream:这行代码会在compose初始化时就执行,而不是调用parse的时候,此时输入参数是undefined,自然会报“无法读取undefined的length属性”的错。
而箭头函数/Reflect.construct的写法,是把“实例化动作”包装成了一个等待接收参数的函数,只有当你调用parse(input)时,每个步骤才会依次执行,正确传递上一步的结果并实例化对应的类。
这样既保留了函数组合的简洁性,又不用额外写辅助函数,完全用原生JS或Lodash FP自带的能力解决了问题~
备注:内容来源于stack exchange,提问作者James Baw
相关产品推荐
相关产品推荐

