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?
- An HTML element's CSS class can be accessed directly from JS thru the className property.
- JS object properties can be accessed via the dot-notation
object.property
or via the square-bracket-notationobject['property']
. - 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 theindexOf
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]()
精彩评论