gpt4 book ai didi

javascript - 迷你 javascript 电子表格系统中 'with' 的替代方案

转载 作者:数据小太阳 更新时间:2023-10-29 06:04:05 24 4
gpt4 key购买 nike

我刚刚遇到了这个我以前从未见过的优雅的 javascript 电子表格代码:http://jsfiddle.net/ondras/hYfN3/

它使用名为 getter 对象的单元格引用作为 DATA 对象的属性,并使用“with”来限定单元格值的评估范围。


//elm.id is the cell reference, DATA is an object whose properties are these getter wrappers
Object.defineProperty(DATA, elm.id, {get:getter});

魔术发生在 getter 中:

    //My comments but jsfiddle code from Ondřej Žára's fiddle 
//Cell value getter function..
var getter = function() {
var value = localStorage[elm.id] || ""; //Direct cell contents
if (value.charAt(0) == "=") { //Got a formula, work it out
//strip the '=' and evaluate recursively with this getter func
with (DATA) return eval(value.substring(1));
} else { // Else just send back the cell contents
return isNaN(parseFloat(value)) ? value : parseFloat(value);
}
};

这是一件美丽的事情,但考虑到“with”即将过时,我想知道是否有一种方法可以在不扩大 DATA 对象范围的情况下简洁地替换用法?

最佳答案

我会避免 witheval 使用 Function 构造函数:

我以前做过类似的事情:

function compile(lexicalScope) {
const params = Object.keys(lexicalScope).join(',');
const values = Object.values(lexicalScope);

return function (expr) {
const compiledFn = new Function(params, '"use strict"; return ' + expr);
return compiledFn.apply(null, values);
};
}

const variables = {A1: 100, B1: 200};

const evaluator = compile(variables);

console.log(evaluator("A1 + B1")); // 300
console.log(evaluator("B1 * 100")); // 20000

基本上我们传递一个对象作为函数的词法范围,我们提取属性名称并将它们传递给 Function 构造函数的第一个参数。

然后在构造函数的主体中,我喜欢首先将函数定义为严格的,因为默认情况下,函数构造函数创建的函数以草率模式运行。

最后,我们简单地返回表达式。之后,我们使用 apply 执行动态函数。

编辑:我查看了电子表格,并对我的方法进行了一些修改,使其适用于此实现。

首先,DATA 对象具有所有不可枚举的 getter,这意味着 Object.keys 不返回任何属性,而不是使用所有可用的属性,我解析表达式中可能出现的标识符,并将它们用作动态函数的可能参数:

function compile(expr) {
// possible parameters for dynamic function
const identifiers = [...new Set(expr.match(/[A-Z]+\d/g))]
const compiledFn = new Function(identifiers, '"use strict"; return ' + expr)
return function(context) {
// extract values
const values = identifiers.map(id => context[id])
return compiledFn(...values)
}
}

这样动态函数将只接收表达式中实际使用的参数。

它是如何工作的?

compile函数实际上是一个函数工厂,当我们用表达式调用它时,例如compile('A1+B2*C3'),它会使用具有以下形式的 Function 构造函数动态生成一个函数:

function anonymous(A1,B2,C3) {
"use strict";
return A1+B2*C3
}

此函数将存储在compile 函数的闭包范围内。返回另一个函数,这个函数接收对象作为参数,属性存储在哪里,取决于表达式中使用的标识符,它提取它们并使用它们来应用我们首先创建的动态函数。

您可以看到一个工作示例 here .

如果我们内存 compile 函数,这可以进一步优化。

感兴趣的可以看this article关于使用 evalnew Function 之间的区别。

关于javascript - 迷你 javascript 电子表格系统中 'with' 的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56224341/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com