简体   繁体   English

javascript 评估如何

[英]javascript eval how to

var obj = {x: 2};变量 obj = {x: 2}; eval.call(obj, 'x'); eval.call(obj, 'x'); // ReferenceError: x is not defined How to change last line to get value by variable name? // ReferenceError: x is not defined 如何更改最后一行以通过变量名获取值?

Clarification澄清
'x' - any expression in some obj context, possibly not a obj parameter 'x' - 某些 obj 上下文中的任何表达式,可能不是 obj 参数

Original problem原来的问题

/**
 * Guards 'this' when delegating method as a callback to others. Arguments aren't known beforehand and will be provided by consumer.
 */
delegate = function(context, func) {
    return function() {
        var args = [];
        for ( var i = 0; i < arguments.length; i++)
            args.push(arguments[i]);
        func.apply(context, args);
    };
};

reference = function (context, 'expression to evaluete to get reference value') {
    ... TODO
};

'delegate' - delegates function call, how to 'delegate a reference' with possibility to 'dereference' in different context? 'delegate' - 代表 function 调用,如何在不同的上下文中“委托引用”并有可能“取消引用”?

Updates更新
here is 2 possibilities to use eval:这里有两种使用 eval 的可能性:
1. eval.call(null, 'evaluate expression in global context'); 1. eval.call(null, '在全局上下文中评估表达式');
2. eval('evaluate expression in context where eval function was called') 2. eval('在调用 eval function 的上下文中评估表达式')
3. how to eval in some predefined 'context'? 3.如何在一些预定义的“上下文”中进行评估?

I want to mimic C++ reference when you can put it in any context and 'dereference' to value (but when in moment you dereference it value could be changed and you should get new value).我想模仿 C++ 参考,当您可以将其放在任何上下文中并“取消引用”值时(但是当您取消引用时,它的值可能会更改并且您应该获得新值)。 Like in javascript you put object as function argument and anytime you get obj.someproperty you'll get newest someproperty value (if it was changed).就像在 javascript 中一样,您将 object 作为 function 参数,并且无论何时您获得 obj.someproperty,您都会获得最新的 someproperty 值(如果已更改)。 But this will not work when you will try to pass a primitive or what if whole object will be changed by some other.但是,当您尝试传递一个原语或者如果整个 object 将被其他一些更改时,这将不起作用。 How to 'pass a reference' to 'whole object' to some other context?如何将“整个对象”的引用“传递给其他上下文”?

Got clear understanding what I want:)清楚地了解我想要什么:)
javascript how to create reference javascript如何创建参考

What I was looking for:我在找什么:

createReference = function(context, prop) {
    return function() {
        return context[prop];
    };
};

Provider = function() {
};
Provider.prototype.x = 5;
Provider.prototype.getXRef = function() {
    return createReference(this, 'x');
};
Provider.prototype.incrementX = function() {
    this.x = this.x + 1;
};

var provider = new Provider();
var refX = provider.getXRef();
provider.incrementX();
alert(refX());

Tanks Brianpeiris!坦克布赖恩佩里斯!

This should do it, no need for eval:这应该可以做到,不需要评估:

var obj = {x: 2};
var value = obj['x'];

Update : I may understand now, or at least I have two guesses.更新:我现在可能明白了,或者至少我有两个猜测。 See Update 1 and Update 2 below.请参阅下面的更新 1更新 2


Original answer :原始答案

You almost never need eval .你几乎不需要eval But just so you know, you're not alone, there are a lot of people who think you have to use eval for this.但是你知道,你并不孤单,有很多人认为你必须为此使用eval It's actually a lot easier than that.它实际上这容易得多。

If you want to access a property in an object, you can use either dotted notation ( obj.x ) or bracketed notation ( obj['x'] ).如果要访问 object 中的属性,可以使用点分表示法 ( obj.x ) 或方括号表示法 ( obj['x'] )。 Note the quotes in the latter: All property names are strings, and the bracket notation lets us use actual strings when looking up properties.请注意后者中的引号:所有属性名称都是字符串,括号表示法允许我们在查找属性时使用实际字符串。 So given this object:所以给定这个 object:

var obj = {foo: 42};

all of these put 42 in x :所有这些都将 42 放入x

x = obj.foo;
x = obj['foo'];
x = obj['f' + 'o' + 'o'];
y = 'foo'; x = obj[y];   // Using the "foo" string from variable `y`
x = obj[getTheAnswer()]; // Using the return value of a function (`getTheAnswer` returns "foo")

As you can see, you can use any expression to come up with the name of the property (as a string), and then use that property name string in the brackets.如您所见,您可以使用任何表达式来得出属性名称(作为字符串),然后在括号中使用该属性名称字符串。


Update 1 : In your reference function, if you literally want to accept a string containing an expression you know nothing about, evaluate the string, and use the result to look up a property on the object, here's how you do that — I want to be clear that I would strongly recommend solving this problem a different way, but without knowing more about the actual problem, I couldn't say how.更新 1 :在您的reference function 中,如果您真的想接受一个包含您一无所知的表达式的字符串,请评估该字符串,并使用结果在 object 上查找一个属性,这就是您的操作方法 — 我想很明显,我强烈建议以不同的方式解决这个问题,但在不了解实际问题的情况下,我不能说如何。 So here it is:所以这里是:

var reference = function(context, expressionString) {
    return context[eval(expressionString)];
};

So for example:例如:

var obj = {p5: 42};
alert(reference(obj, "'p' + (4 + 1)")); // alerts 42

Live example活生生的例子

Apologies if I've guessed wrong.抱歉,如果我猜错了。


Update 2 :更新 2

From the fact that you're giving delegate and reference together, and the comment "... how to 'delegate a reference' with possibility to 'dereference' in different context?..." it sounds like you're trying to find a way to find out what the original function was, if you only have the delegate.从您将delegatereference一起提供的事实以及评论“......如何在不同的上下文中'取消参考'的可能性'委托参考'?......”听起来你正在试图找到一种找出原始function 是什么的方法,如果你只有代表的话。 Eg:例如:

function foo() { ... }
var fooDelegate = delegate(someObject, foo);
var original = reference(someObject, fooDelegate);
alert(original === foo); // alerts true

If that's what you're trying to do, you can't do it without setting something up in delegate that you later look for in reference .如果就是您想要做的事情,那么您必须在delegate中设置一些您稍后在reference中查找的内容。 Fortunately, that's easy:幸运的是,这很容易:

// Create a function that, when called, will always call the given
// function with the given context, passing along the call arguments.
delegate = function(context, func) {
    var newFunc = function() {
        return func.apply(context, arguments);
    };
    newFunc.__delegate__original = func;
    return newFunc;
};

// If given a function created by `delegate`, returns the original
// underlying function. If the given function is not from `delegate`,
// returns `func` unchanged.
reference = function(func) {
    return func.__delegate__original || func;
};

Note that you don't need the context parameter on reference.请注意,您不需要在reference.时使用context参数。

And again, apologies if I'm guessing wrong.如果我猜错了,再次道歉。


Off-topic : Re your delegate function, you'll be glad to know that you don't have to copy the arguments before you pass them into apply .题外话:作为您的delegate function,您会很高兴知道您不必在将arguments传递给apply之前复制它们。 (You do probably want to return the return value of the target function, though.) This works fine cross-implementation: (不过,您可能确实希望返回目标 function 的返回值。)这很好地交叉实现:

delegate = function(context, func) {
    return function() {
        return func.apply(context, arguments);
    };
};

...because apply is carefully defined in the specification to allow any array-like object, it doesn't require an actual Array instance. ...因为在规范中仔细定义了apply以允许任何类似数组的 object,它不需要实际的Array实例。 See Section 15.3.4.3 of the spec for details.有关详细信息,请参阅规范的第 15.3.4.3 节。

To extend @brianpeiris's answer, you can decide what parameter you want to read from the object dynamically, at runtime.要扩展@brianpeiris 的答案,您可以决定在运行时动态地从 object 读取什么参数。 For example:例如:

var obj = {x: 2);
var field = 'x'; // or do some other operation to figure out the field you want
var value = obj[field];
if (value) {
  // the field exists and has a true value
} 

Or, if you absolutely have to use eval:或者,如果您绝对必须使用 eval:


var obj = {x : 2};
var myVar = eval(obj.x);
alert(myVar);

Overkill, I know.矫枉过正,我知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM