开发者

How to remove eval() from dynamic property calls and Uncaught ReferanceError

I'm trying to call object properties dynamically. I have solved the problem with eval() but i know that eval is evil and i want to do this on a better and safer way. My eval code:

            // onfocus
            var classes = this.getAttribute('class').split(' ');
            for(var i = 0; i < classes.length; ++i) {
                if(classes[i].match(/val\- */) !== null) {
                    var rule = classes[i].substr(4);
                    var instruction = eval('validate.instructionTexts.'+ rule +'()');

                    tooltip.appendChild( document.createTextNode(instruction) );
                }
            } 

And I also have this code:

       // onblur
        var classes = this.getAttribute('class').split(' ');
        for( var i = 0; i < classes.length; ++i ){
            if(classes[i].match(/val\- */) !== null) {
                var rule = classes[ i ].substr( 4 );
                var tooltip = document.getElementsByClassName( 'tooltip' );
                for( i = 0; i < tooltip.length; ++i){
                    tooltip[ i ].style.display = 'none';
                }

                eval('validate.rules.'+ rule +'(' + (this.value开发者_如何学运维) + ')');
            }

the problem with the second code is that I want to send a string to my property. this.value = the text i type in my textbox so i get correct string from this.value but i got this error.

if i type foo. Uncaught ReferenceError: foo is not defined. Javascript thinks I trying to send a variabel but i want it to send a string. How can i solve this problems?


  1. An HTML element's CSS class can be accessed directly from JS thru the className property.
  2. JS object properties can be accessed via the dot-notation object.property or via the square-bracket-notation object['property'].
  3. The regex /val\- */ matches the characters v, a, l, a '-' hyphen, and zero or more spaces, anywhere in the string.
    • The spaces are completely irrelevant since you're testing the result of a string that was split on spaces (and so it won't contain any spaces anymore).
    • Also, you're not anchoring the regex so a class of 'eval-test' will also be matched. I doubt that's what you're looking for.
    • If you were just testing for the classes starting with val-, then the indexOf method is much easier to read, and probably also a lot more efficient.

I've adjusted your bits of code accordingly. I'm assuming that the class names for your validation rules all start with val-, and that the rest of the class name is the name for the rule:

// onfocus
var classes = this.className.split(' ');
for(var i = 0; i < classes.length; ++i) {
    if(classes[i].indexOf('val-') === 0) { // the class name starts with 'val-'
        var rule = classes[i].substr(4);
        var instruction = validate.instructionTexts[rule]();

        tooltip.appendChild(document.createTextNode(instruction));
    }
}


// onblur
var classes = this.className.split(' ');
for (var i = 0; i < classes.length; ++i ){
    if(classes[i].indexOf('val-') === 0) { // the class name starts with 'val-'
        var rule = classes[i].substr(4);
        var tooltip = document.getElementsByClassName('tooltip');
        for (i = 0; i < tooltip.length; ++i){
            tooltip[i].style.display = 'none';
        }

        validate.rules[rule](this.value);
    }
}


You do not need to use eval, you can access it as:

validate.rules[rule](this.value);

Which will solve your other problem too, which is that you are passing in the value of this.value which when eval()'d is not quoted as a string (which 'foo' is) so is being interpreted as a variable.


to get a property foo from object obj, you could use either

obj.foo

or

obj["foo"]

The first one won't allow reserved words or if the property contains spaces.

So your first example could change to

validate.instructionTexts[rule]()
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜