JavaScript快速入门:计算方法
您可能知道对象中的计算键,但您是否意识到可以使用方法简写来使用计算键?您可能永远都不想这样做。
const methodName = 'myMethod'; const computedKey = 'computed'; const myObj = { // Computed Property [computedKey]: 'It worked!', // 🤔 Is this a good idea? Probably not, no. // Computed property + Method shorthand [methodName]() { return this.computed; }, }; myObj.myMethod(); // 'It worked!'
历史课
在 JavaScript 的早期版本中,所有函数都是在全局范围内定义的。即使在那时,你也可以使用括号来获取或设置计算值,但我们想到的大多数功能都无法实现。
ECMAScript 3
ECMAScript 3 为我们带来了函数表达式和对象方法。您可以使用括号表示法来设置属性或方法。
// Old JavaScript. var computedKey = 'computed'; var myObj = { // Key and function separately. myMethod: function () { return this.computed; }, }; myObj[computedKey] = 'It worked!'; myObj.myMethod(); // 'It worked!'
如果您愿意,可以使用动态方法名称,但它们必须在创建对象后定义。
myObj = {}; myObj[methodName] = function() { return this.computed; };
ECMAScript 2015
ECMAScript 2015 引入了对象方法简写和计算属性。
// Exciting new JavaScript! const computedKey = 'computed'; const myObj = { // Method shorthand myMethod() { return this.computed; }, // Computed Property [computedKey]: 'It worked!', }; myObj.myMethod(); // 'It worked!'
尽管 MDN 文章没有特别提到,但您可以将方法简写与计算属性名称混合使用,如文章开头所示。
问题
在某些极端情况下,这样做是有意义的,但一般来说,我们应该避免使用这种技术。当试图理解代码时,它会使查找方法变得非常困难,并降低代码编辑器支持的有效性,如 IntelliSense 和类型信息。
替代方案
哈希或代理可以很好地替代计算方法名称。看看我们可以实现这一点的一些方法,然后让我知道您认为哪种方法最适合您!
通用代码
下面的所有示例都是用顶部的这几行代码编写和测试的。如果您在控制台、REPL 或 RunJS 中运行这些示例,则可以看到它们可以正常工作。
const methodName = 'myMethod'; const computedKey = 'computed'; const myObj = { getComputed() { return this.computed; }, [computedKey]: 'It worked!', };
平原地图
用于匹配方法名称的简单字符串映射几乎不需要设置,但却使得调用方法变得有点困难。
const methodMap = { [methodName]: 'getComputed', }; myObj[methodMap.myMethod](); // 'It worked!';
边界映射
使用与原始对象绑定的方法的对象需要更多设置,但可以简化消费者的代码。
const methodMapBound = { [methodName]: myObj.getComputed.bind(myObj), }; methodMapBound.myMethod(); // 'It worked!'
基本代理
Proxy 对象消除了大部分复杂性,因为您可以直接与代理交互。这使用 getter 中的静态检查来查找我们的计算属性。
const basicProxy = new Proxy(myObj, { get(target, prop, receiver) { if (prop === methodName) { return myObj.getComputed; } return Reflect.get(...arguments); }, }); basicProxy.myMethod(); // 'It worked!'
代理加地图
使用 Plain Mapping 示例中的属性名映射 a,我们可以支持任意数量的方法映射。如果我们愿意接受一点无限循环的风险,我们实际上可以支持多个间接引用!
const methodMap = { [methodName]: 'getComputed', 'thisIsWild': methodName, }; const methodProxy = new Proxy(myObj, { get(target, prop, receiver) { if (methodMap[prop]) { // Using receiver allows multiple indirection return receiver[methodMap[prop]]; } return Reflect.get(...arguments); }, }); methodProxy.myMethod(); // 'It worked!' methodProxy.thisIsWild(); // 'It worked!'
结论
我希望您喜欢这篇简短的文章,了解一些意想不到的和(希望)未使用的 JavaScript 功能!