2014-10-10 38 views
0

我已將自己的JavaScript包裝在自調用函數中以保持所有內容。 Hoever,我遇到了一個問題,即我的鏈接動態構建,在點擊時返回一個錯誤「Function not defined」。讓我有我的相關代碼:具有動態綁定內容的自調用函數範圍

(function(window, document, $) { 

    function buildChapterList() { 
     for(var i=0; i<Object.keys(theChapterCues).length; i++) { 
      chapterListHTML = "<li><a class='fun-blue' href='javascript:void(0)' onClick=\"skipToChapter('"+ i +"')\">"+ theChapterCues[i]["title"] +"</a></li>"; 
      $(chapterListHTML).appendTo("ul#chapter-list"); 
      $("body").bind("DOMNodeInserted", function() { 
       $(this).find('#chapter-list li').first().addClass("active"); 
      }); 
     } 
    } 
    function skipToChapter(theChapter) { 
     if (theChapter == 0) { 
      theVideo.currentTime=0; 
     } else { 
      var thisChapterStart = parseInt(cues[theChapter]["chapterStart"]+1); 
      theVideo.currentTime=thisChapterStart/frameRate; 
     } 
    } 

}(this, this.document, this.jQuery)); 

當點擊我收到以下錯誤生成的鏈接之一:

未捕獲的ReferenceError:我失去了對範圍的東西skipToChapter沒有定義

?這是一個有約束力的問題?任何建議將不勝感激。謝謝!

+0

是的,你的功能只存在於你的匿名範圍內。你需要在全局範圍內使用它,或者找到另一種綁定事件的方法(如果你可以提供小提琴,會更容易找到另一種方法) – 2014-10-10 14:16:12

回答

2

skipToChapter函數只在外部匿名函數中可見。你可以在這裏閱讀關於Javascript的範圍:http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/

解決這個問題的快速和骯髒的方法將是定義skipToChapter匿名函數之外或作爲窗口對象的成員。

例如:

window.skipToChapter = function(theChapter) { 
    if (theChapter == 0) { 
     theVideo.currentTime=0; 
    } else { 
     var thisChapterStart = parseInt(cues[theChapter]["chapterStart"]+1); 
     theVideo.currentTime=thisChapterStart/frameRate; 
    } 
} 

然而,要知道,這是不是一個功能結合事件的最佳實踐,因爲它使skipToChapter全球和使用內聯事件處理程序(http://robertnyman.com/2008/11/20/why-inline-css-and-javascript-code-is-such-a-bad-thing/)。

一個更好的辦法是:

function buildChapterList() { 
    for(var i=0; i<Object.keys(theChapterCues).length; i++) { 
     chapterListHTML = "<li><a class='fun-blue' href='javascript:void(0)' data-index='" + i + "'>"+ theChapterCues[i]["title"] +"</a></li>"; 
     var $chapterListHTML = $(chapterListHTML); 
     $chapterListHTML.appendTo("ul#chapter-list"); 
     $chapterListHTML.find('a').click(skipToChapter); 
     $("body").bind("DOMNodeInserted", function() { 
      $(this).find('#chapter-list li').first().addClass("active"); 
     }); 
    } 
} 
function skipToChapter() { 
    var theChapter = $(this).data('index'); 
    if (theChapter == 0) { 
     theVideo.currentTime=0; 
    } else { 
     var thisChapterStart = parseInt(cues[theChapter]["chapterStart"]+1); 
     theVideo.currentTime=thisChapterStart/frameRate; 
    } 
} 

閱讀這個答案的詳細信息,事件綁定在dinamically創建的元素,用jQuery:Event binding on dynamically created elements?

+0

這對我有效,但不能將其標記爲答案。你能再詳細說明爲什麼會發生這種情況嗎?爲什麼這會修復它或者指向我可以閱讀的文章? – Yuschick 2014-10-10 14:19:10

+3

-1使用全局變量和內聯處理函數。 – Bergi 2014-10-10 14:29:15

+0

我的'全局'變量都包含在我的匿名函數中,只是沒有包含在我的原始文章中的代碼中。我現在正在學習更好的替代內聯處理程序。所以學習新事物的道德準則+1。 – Yuschick 2014-10-10 14:45:07

3

skipToChapter功能在全球範圍內,所以不能從內聯點擊處理程序調用。相反,您應該在建立鏈接時分配點擊處理程序,並採用如下所示的不顯眼的方式。如果你這樣指定,那麼skipToChapter就在範圍之內,你不必將它設爲全局的,並且你不需要不需要的內聯事件處理程序。

function buildChapterList() { 
    for(var i=0; i<Object.keys(theChapterCues).length; i++) { 
     chapterListHTML = $("<li><a class='fun-blue' href='javascript:void(0)'>"+ theChapterCues[i]["title"] +"</a></li>"); 
     (function(i){ 
      chapterListHTML.find('a').click(skipToChapter.bind(this, i)); 
     })(i); 
     chapterListHTML.appendTo("ul#chapter-list"); 
     $("body").bind("DOMNodeInserted", function() { 
      $(this).find('#chapter-list li').first().addClass("active"); 
     }); 
    } 
} 
+0

謝謝你的解釋。這是一個非常乾淨的解決方案,看起來像一個不斷前進的良好實踐。 – Yuschick 2014-10-10 14:42:34

+0

該解決方案在循環內定義了一個函數,這不是一個好習慣。 – ncardeli 2014-10-10 14:52:07

+0

循環中的函數是不好的做法?來自使用全局和內聯事件處理程序發佈答案的人.....好吧。 – MrCode 2014-10-10 14:54:57