(我基礎沒打好,所以說不定這問題根本不是問題 ...)
果然是很基礎的問題:
Javascript 的 eval 行為與 function pointer
在 http://html5boilerplate.com 的環境下,我寫了這段 javascript 在 script.js 檔:
Test 1
(function($){ $(document).ready(function(){ function sayHi() { console.log('hello'); } $(function() { setInterval( "sayHi()", 2000 ); }); }); // end of $(document).ready }(jQuery)); // end of all在執行的時候,Firefox 說:sayHi is not defined
Test 2
(function($){ $(document).ready(function(){ $(function(){ function sayHi() { console.log('hello'); } setInterval( "sayHi()", 2000 ); }); }); // end of $(document).ready }(jQuery)); // end of all一樣是 sayHi is not defined.
因為 sayHi() 是在:
(function($){ 底下的 ...
$(document).ready(function(){ 底下的 ...
$(function(){ 底下的 scope 內,
而使用雙引號 "sayHi()" 呼叫時,Javascript 會尋找全域環境下的 sayHi(),當然找不到。
Test 3
(function($){ $(document).ready(function(){ $(function(){ function sayHi() { console.log('hello'); } setInterval( sayHi(), 2000 ); }); }); // end of $(document).ready }(jQuery)); // end of all可以執行,但是只執行一次。
因為呼叫時加了 () 等於是執行這個 function,而不是 refer 到這個 function 而不執行。
function 在 Javascript 是類似 object(打類比成 Linux 把所有東西看成檔案一樣)。
Test 4
(function($){ $(document).ready(function(){ $(function(){ function sayHi() { console.log('hello'); } setInterval( sayHi, 2000 ); }); }); // end of $(document).ready }(jQuery)); // end of allit works.
sayHi function 的 scope 在:
(function($){ 底下的 ...
$(document).ready(function(){ 底下的 ...
$(function(){ 底下。
setInterval 內的 sayHi refer 到同一層的 sayHi function(object?)
Test 5
(function($){ $(document).ready(function(){ $(function() { setInterval( function(){ console.log('hello'); }, 2000 ); }); }); // end of $(document).ready }(jQuery)); // end of allit works.
直接綁定一個匿名函式,沒有問題。
Test 6
(function($){ $(document).ready(function(){ function sayHi() { console.log('hello'); } $(function() { setInterval( sayHi, 2000 ); }); }); // end of $(document).ready }(jQuery)); // end of allit works!?
Test 7
function sayHi() { console.log('hello'); } $(function() { setInterval( "sayHi()", 2000 ); });it works.
(function($){ 與 $(document).ready(function(){ 都要拿掉,留下任何一個也不行。
如此一來,宣告的 sayHi function 才是在全域範圍下,"sayHi()" 才 refer 得到。
最後,如果要宣告一個全域的 Javascript function,
或是說“假裝”成 Class 那樣用(Javascript 是 classless 的!),
可以這樣做:
var ClassName = window.ClassName = function() { // your code }; ClassName.prototype.method_of_class = function() { // your code };
function pointer
function scope
Reference:
http://stackoverflow.com/questions/1191833/how-to-run-a-function-in-jquery
http://jquery-howto.blogspot.com/2008/12/what-heck-is-function-jquery.html
http://jibbering.com/faq/notes/closures/
http://www.javascriptkit.com/javatutors/closures.shtml
http://www.robertsosinski.com/2009/04/28/binding-scope-in-javascript/
http://audi.tw/Blog/JavaScript/javascript.eval.asp
http://24ways.org/2005/dont-be-eval
http://docs.jquery.com/How_jQuery_Works
http://jquery-howto.blogspot.com/2008/12/what-heck-is-function-jquery.html
沒有留言:
張貼留言