我有以下javaScript"class":
A = (function() {
a = function() { eval(...) };
A.prototype.b = function(arg1, arg2) { /* do something... */};
})();
Run Code Online (Sandbox Code Playgroud)
现在让我们假设在eval()中我传递的字符串包含调用带有一些参数的表达式:
b("foo", "bar")
Run Code Online (Sandbox Code Playgroud)
但后来我得到b没有定义的错误.所以我的问题是:如何在A类语境中调用eval?
Cam*_*eln 61
实际上你可以通过函数抽象来完成这个:
var context = { a: 1, b: 2, c: 3 };
function example() {
console.log(this);
}
function evalInContext() {
console.log(this); //# .logs `{ a: 1, b: 2, c: 3 }`
eval("example()"); //# .logs `{ a: 1, b: 2, c: 3 }` inside example()
}
evalInContext.call(context);
Run Code Online (Sandbox Code Playgroud)
所以你想要call
的功能context
和eval
在该功能内运行.
对于简洁(可以说是多汁的)版本,您可以逐字复制到您的代码中,使用:
function evalInContext(js, context) {
//# Return the results of the in-line anonymous function we .call with the passed context
return function() { return eval(js); }.call(context);
}
Run Code Online (Sandbox Code Playgroud)
use*_*385 29
如何在给定的上下文中调用eval?3个字.使用封闭物.
var result = function(str){
return eval(str);
}.call(context,somestring);
Run Code Online (Sandbox Code Playgroud)
巴姆.
eve*_*Guy 17
即使eval.call和eval.apply不强制正确传递上下文,您也可以使用闭包来强制eval在所需的上下文中执行,如@Campbeln和@ user3751385的答案中所述
这是不可能的.Eval仅在本地上下文中使用(直接使用)或在全局上下文中调用(即使您使用eval.call).
例如,
a = {};
eval.call(a, "console.log(this);"); //prints out window, not a
有关更多信息,请在此处查看这篇精彩的文章
绝对不是正确的答案,请不要使用with
声明,除非你知道你在做什么,但对于好奇,你可以这样做
var a = {b: "foo"};
with(a) {
// prints "foo"
console.log(eval("b"));
// however, "this.b" prints undefined
console.log(eval("this.b"));
// because "this" is still the window for eval
// console.log(eval("this")); // prints window
// if you want to fix, you need to wrap with a function, as the main answer pointed out
(function(){
console.log(eval("this.b")); // prints foo
}).call(a);
}
// so if you want to support both
with (a) {
(function (){
console.log("--fix--");
console.log(eval("b")); // foo
console.log(eval("this.b")); // foo
}).call(a);
}
Run Code Online (Sandbox Code Playgroud)
with
是在功能中创建块范围的尝试失败,这是ES6的let
目的.(但不完全是,打开并阅读资源链接)
所以我们在 2020 年,我有这个要求,不幸的是,大多数答案根本不适合这项任务。
您可能可以跳过这一部分,但要解释情况……这是一个更完整的答案。
调用 eval 很糟糕......在这里我正试图做到这一点......不是因为我想要而是因为有人强迫我这样做......我的另一个选择是编译提取物和AST并最终评估a的上下文价值...但 eval 除了其自身的邪恶性质之外,它确实是完成任务的工具...
所以我们开始了,mdn 文档:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
简而言之, eval 曾经可以工作,现在它变得更加难以使用,因为评估的上下文将成为全局上下文,因此在某些情况下不可能获得this
. 并且由于某些原因,它看起来似乎无法this
使用此问题的答案获得as 评估上下文。所以进一步阅读我们到达了文章的第二部分..
文章的第二部分以“永远不要使用 eval()!”开头。, 收到消息!进一步阅读我们得出以下结论:
幸运的是,有一个非常好的 eval() 替代方法:只需使用 window.Function()。
好!
所以看代码的接缝非常好... 大多数例子只是简单地创建一个函数调用它并把它扔掉。这几乎就是 eval 的工作方式,所以你也可以这样做......
但对我来说, eval 上下文可以重复使用,并且可能经常重复使用,所以我想出了这个。
function create_context_function_template(eval_string, context) {
return `
return function (context) {
"use strict";
${Object.keys(context).length > 0
? `let ${Object.keys(context).map((key) => ` ${key} = context['${key}']`)};`
: ``
}
return ${eval_string};
}
`
}
Run Code Online (Sandbox Code Playgroud)
这将编译一个函数,该函数接收要在给定特定上下文的情况下进行评估的上下文。这对于您知道评估上下文将始终包含一组特定键的情况很有用......
该函数的第一行通过从作为参数传递的上下文中获取值来生成局部范围内声明变量的列表。
这将在给定上下文的情况下呈现如下所示的 JS 代码: {a: 1, b: 2}
let a = context['a'], b = context['b'];
Run Code Online (Sandbox Code Playgroud)
第二行是您要评估的上下文,例如“a + b”
它将呈现以下代码:
return a + b
Run Code Online (Sandbox Code Playgroud)
总而言之,有这个实用方法:
function make_context_evaluator(eval_string, context) {
let template = create_context_function_template(eval_string, context)
let functor = Function(template)
return functor()
}
Run Code Online (Sandbox Code Playgroud)
这只是将它包装起来并返回我们需要的函子......
let context = {b: (a, b) => console.log(a, b)}
let evaluator = make_context_evaluator("b('foo', 'bar')", context)
let result = evaluator(context)
Run Code Online (Sandbox Code Playgroud)
关于它的好处是,如果您想继续使用评估器,因为您知道您不会对评估上下文进行太多更改......然后您可以保存评估器并在不同的上下文中重用它..
在我的情况下,它是根据一些记录评估上下文,因此字段集相同但值不同......因此可以重用该方法而无需编译多个方法......另一方面,据说它比使用更快eval
,我们没有评估任何东西。如果传递给 的值Function
会尝试在其范围之外使用事物......它的危害会小于eval
......例如,它可以访问全局范围但不应该访问词法范围。换句话说......你被限制在全局范围内,并且 this 传递给调用参数。
然后,如果您真的想将它用作类似 eval 的函数,您可以这样做:
function create_context_function_template(eval_string, context) {
return `
return function (context) {
"use strict";
${Object.keys(context).length > 0
? `let ${Object.keys(context).map((key) => ` ${key} = context['${key}']`)};`
: ``
}
return ${eval_string};
}
`
}
function make_context_evaluator(eval_string, context) {
let template = create_context_function_template(eval_string, context)
let functor = Function(template)
return functor()
}
function eval_like(text, context={}) {
let evaluator = make_context_evaluator(text, context)
return evaluator(context)
}
Run Code Online (Sandbox Code Playgroud)
这是一篇讨论eval()
在不同背景下运行的文章:
http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
通常你用eval.call()
或做eval.apply()
.
以下是有关eval()
其用例的信息:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/eval
这解决了我的问题。
function evalInContext(js, context) {
return function(str){
return eval(str);
}.call(context, ' with(this) { ' + js + ' } ');
}
Run Code Online (Sandbox Code Playgroud)
用于类似于“Dom-if”的实现
<template if="{{varInContext == ''}}"> ... </template>
Run Code Online (Sandbox Code Playgroud)
例子
var myCtx = {table: 'Product', alias: 'ProductView'};
evalInContext(' table == "" ', myCtx); //#false
evalInContext(' alias == "ProductView" ', myCtx); //#true
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
41728 次 |
最近记录: |