2011-09-12 108 views
0

爲什麼我在alert請致電undefJavascript:可變範圍問題

#!/usr/bin/env perl 
use warnings; 
use 5.014; 
use utf8; 
use Mojolicious::Lite; 
use DBI; 

my $db = 'my_test_db.db'; 
my $table = 'my_test_table'; 
my $dbh = DBI->connect("dbi:SQLite:dbname=$db", '', '', 
      { RaiseError => 1, PrintError => 0, AutoCommit => 1, sqlite_unicode => 1, } 
     ) or die $DBI::errstr; 
$dbh->do("CREATE TEMP TABLE $table (str TEXT, num INTEGER)"); 
my $sth = $dbh->prepare("INSERT INTO $table (str, num) VALUES (?, ?)"); 
$sth->execute('aaa', '111'); 
$sth->execute('bbb', '222'); 
$sth->execute('ccc', '333'); 

get '/eingabe' => sub { 
    my $self = shift; 
    $self->render('eingabe'); 
}; 

get '/search_db/:col' => sub { 
    my $self = shift; 
    my $col = $self->param('col'); 
    my $term = $self->param('term'); 
    my $sth = $dbh->prepare("SELECT DISTINCT $col FROM $table WHERE $col LIKE ?"); 
    $sth->execute($term . '%'); 
    my $ref; 
    while (my $row = $sth->fetchrow_arrayref()) { 
      push @$ref, @$row; 
    } 
    $self->render(json => $ref); 
}; 

app->start; 

__DATA__ 
@@ eingabe.html.ep 
<!DOCTYPE HTML> 
<html> 
<head> 
<meta charset="UTF-8" /> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script> 
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js"></script> 
<script type="text/javascript"> 
    $(document).ready(function() { 
     var ids = [ 'str', 'num' ]; 
     for (var i = 0; i < ids.length; i++){ 
      $("#" + ids[i]).autocomplete({ 
       source: function(request, response){ 

        alert(ids[i]); // <--- 

        $.getJSON('/search_db/' + ids[i], request, function(data_from_server){ 
         var suggestions = []; 
         var len = data_from_server.length; 
         for(var i = 0; i < len; i++){ 
          suggestions.push(data_from_server[i]); 
         } 
         response(suggestions); 
        }); 
       } 
      }); 
     } 
    }); 
</script> 
</head> 
<body> 
<form> 
    <table> 
     <tr><td>String:</td><td><input type="text" id="str" name="str"" /></td></tr> 
     <tr><td>Number:</td><td><input type="number" id="num" name="num" /></td></tr> 
    </table><br /> 
    <input type="submit" value="OK"/> 
</form> 
</body> 
</html> 

回答

3

這聽起來像你遇到的是在這裏說明了問題:Creating closures in loops: A common mistake

爲什麼你要undefined在調用alert其原因在於,當autocomplete函數被調用,您的for循環已完成執行含義爲你的循環變量i的值爲2即ids.length + 1。因此ids[i]ids[2]相同,因爲您的ids陣列中只有2個元素,所以不存在。我試圖想出一個這種行爲的簡單演示來幫助說明發生了什麼:http://jsfiddle.net/ianoxley/KwXVs/1/(您需要打開瀏覽器的控制檯才能看到結果)。

如果您創建一個額外的封閉件,應該有助於保留範圍並擺脫undefined(請參閱http://jsfiddle.net/ianoxley/BVa5Q/)。

如果你嘗試改變你的代碼是這樣希望它能擺脫問題:

$(document).ready(function() { 
    function initAutocomplete(element_id) { 
     $("#" + element_id).autocomplete({ 
      source: function (request, response) { 

       alert(element_id); // <--- 

       $.getJSON('/search_db/' + element_id, request, function (data_from_server) { 
        var suggestions = []; 
        var len = data_from_server.length; 
        for (var i = 0; i < len; i++) { 
         suggestions.push(data_from_server[i]); 
        } 
        response(suggestions); 
       }); 
      } 
     });   
    } 

    var ids = ['str', 'num']; 
    for (var i = 0; i < ids.length; i++) { 
     var current_id = ids[i]; 
     initAutocomplete(current_id); 
    } 
}); 

希望這有助於。

+0

是的,這就是我想說的,但我很着急。很好的解釋。 –

0

你兩次定義i迭代變量:這是你的回調$.getJSON呼叫內再次使用。

你應該重新命名一個不同的名字,j(只是一個例子)。

所以它會說:

$(document).ready(function() { 
    var ids = [ 'str', 'num' ]; 
    for (var i = 0; i < ids.length; i++){ 
     $("#" + ids[i]).autocomplete({ 
      source: function(request, response){ 

       alert(ids[i]); // <--- 

       $.getJSON('/search_db/' + ids[i], request, function(data_from_server){ 
        var suggestions = []; 
        var len = data_from_server.length; 
        for(var j = 0; j < len; j++){ 
         suggestions.push(data_from_server[j]); 
        } 
        response(suggestions); 
       }); 
      } 
     }); 
    } 
}); 

我希望這有助於!

+0

沒有看到,通常我不會那樣做。但據我所知,在JavaScript中,變量的範圍是一個函數,所以在我的理論中,第二個'var i'應該與聲明第二個'var i'的函數之外的第一個'var i'混淆。 –

0

你的回調函數超出了範圍。當你對一個事件鏈接進行攻擊時,當你的for循環完成之後,當事件被觸發時它會被調用。

每當你使用回調時,一個好的經驗法則是總是傳遞該函數需要的所有東西,或者將對象需要的所有東西附加到窗口對象並將其全局化。