在JavaScript中将API返回的完整函数字符串转为可执行函数的问题
Excel Office JS任务窗格:执行API返回的异步函数字符串问题
问题场景
开发Excel Office JavaScript任务窗格时,点击按钮调用外部API得到完整的异步函数字符串,使用new Function(response)转换后调用无反应。调试发现new Function()会将完整函数定义包裹进一层匿名函数,导致实际定义的highlightCells函数从未被执行。
API返回的字符串内容:
async function highlightCells() { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sheet1"); const range = sheet.getRange(); range.format.fill.color = "yellow"; await context.sync(); console.log("Called"); }); }
经new Function()转换后的实际结构:
function anonymous() { async function highlightCells() { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sheet1"); const range = sheet.getRange(); range.format.fill.color = "yellow"; await context.sync(); console.log("Called"); }); } }
解决方案
方法1:追加函数调用后用eval执行
在API返回的函数定义字符串末尾追加函数调用语句,直接通过eval执行完整代码:
const apiResponse = `async function highlightCells() { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sheet1"); const range = sheet.getRange(); range.format.fill.color = "yellow"; await context.sync(); console.log("Called"); }); }`; // 追加函数调用 const executableCode = apiResponse + "\nhighlightCells();"; eval(executableCode);
方法2:修改字符串让new Function返回目标函数
将原函数定义转换为函数表达式,让new Function()返回该函数后直接调用:
const apiResponse = `async function highlightCells() { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sheet1"); const range = sheet.getRange(); range.format.fill.color = "yellow"; await context.sync(); console.log("Called"); }); }`; // 将函数定义转为返回表达式 const functionWrapper = `return ${apiResponse.replace(/^async function (\w+)/, 'async function')}`; const targetFunction = new Function(functionWrapper)(); // 调用异步函数 await targetFunction();
方法3:提取函数体创建新函数
通过正则提取原函数的函数体内容,用new Function()直接创建异步函数并调用:
const apiResponse = `async function highlightCells() { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sheet1"); const range = sheet.getRange(); range.format.fill.color = "yellow"; await context.sync(); console.log("Called"); }); }`; // 正则匹配提取函数体 const bodyMatch = apiResponse.match(/async function \w+\(\) {([\s\S]+)}/); if (bodyMatch) { const functionBody = bodyMatch[1]; const highlightCells = new Function('', `return async function() {${functionBody}}`)(); await highlightCells(); }
安全提示
执行外部来源的代码存在XSS注入风险,必须确保API返回的内容完全可信,避免引入恶意代码。
内容的提问来源于stack exchange,提问作者Calleb213
相关产品推荐
相关产品推荐

