最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript eval how to - Stack Overflow

programmeradmin2浏览0评论

var obj = {x : 2}; eval.call(obj, 'x'); // ReferenceError: x is not defined How to change last line to get value by variable name?

Clarification
'x' - any expression in some obj context, possibly not a obj parameter

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?

Updates
here is 2 possibilities to use eval:
1. eval.call(null, 'evaluate expression in global context');
2. eval('evaluate expression in context where eval function was called')
3. how to eval in some predefined 'context' ?

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). 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). But this will not work when you will try to pass a primitive or what if whole object will be changed by some other. How to 'pass a reference' to 'whole object' to some other context?

Got clear understanding what I want :)
javascript how to create reference

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!

var obj = {x : 2}; eval.call(obj, 'x'); // ReferenceError: x is not defined How to change last line to get value by variable name?

Clarification
'x' - any expression in some obj context, possibly not a obj parameter

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?

Updates
here is 2 possibilities to use eval:
1. eval.call(null, 'evaluate expression in global context');
2. eval('evaluate expression in context where eval function was called')
3. how to eval in some predefined 'context' ?

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). 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). But this will not work when you will try to pass a primitive or what if whole object will be changed by some other. How to 'pass a reference' to 'whole object' to some other context?

Got clear understanding what I want :)
javascript how to create reference

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!

Share Improve this question edited May 23, 2017 at 10:24 CommunityBot 11 silver badge asked Apr 27, 2011 at 20:41 Mykhaylo AdamovychMykhaylo Adamovych 21k26 gold badges109 silver badges148 bronze badges 11
  • 4 What is the problem with obj.x ? Or obj['x'] ? – Felix Kling Commented Apr 27, 2011 at 20:43
  • 7 I'm not sure what you are actually trying to achieve, but the way you are going about it is horrible. Take a step back and explain the problem you are trying to solve with this syntax (instead of trying figure out how to get the syntax to work). – Quentin Commented Apr 27, 2011 at 20:44
  • 1 @Mykhaylo: Again, to David's point, can you explain more clearly what you're trying to achieve? Because there will be a better way than eval. – T.J. Crowder Commented Apr 27, 2011 at 20:48
  • 2 Here’s something to read: Global eval. What are the options? – Gumbo Commented Apr 27, 2011 at 20:51
  • 3 @Mykhaylo: Your "Original problem" code doesn't explain what you want to do. The delegate function seems pletely unrelated, as it never calls reference. The reference function doesn't give enough information to explain why the several answers below aren't what you're looking for. – T.J. Crowder Commented Apr 27, 2011 at 20:59
 |  Show 6 more ments

4 Answers 4

Reset to default 5

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.


Original answer:

You almost never need 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. 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']). 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:

var obj = {foo: 42};

all of these put 42 in 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 e 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 remend solving this problem a different way, but without knowing more about the actual problem, I couldn't say how. 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:

From the fact that you're giving delegate and reference together, and the ment "... 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. E.g.:

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. 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.

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. (You do probably want to return the return value of the target function, though.) This works fine cross-implementation:

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. See Section 15.3.4.3 of the spec for details.

To extend @brianpeiris's answer, you can decide what parameter you want to read from the object dynamically, at runtime. 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:

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

Overkill, I know.

发布评论

评论列表(0)

  1. 暂无评论