目錄 • 參數傳遞 • JavaScript調用Flash方法 • 方法的效能最佳化 參數傳遞迴目錄
當JavaScript調用一個Flash方法的時候,FlashPlayer會將參數轉換成XML格式,而轉換函式實際上在Flash嵌入到頁面並且被正確載入的時候就被拋出到了全域上:
__flash__argumentsToXML 用於將參數轉換成XML表達的方法 __flash__arrayToXML 用於將數群組轉換成XML __flash__escapeXML 用於將XML內的字元轉義 __flash__objectToXML 用於將Object轉換成XML __flash__request 用於組成請求體 __flash__toXML 用於將資料轉換成XML
實際上JavaScript 和 Flash 程式之間只能傳遞字串資料,任何類型的資料都通過上面的轉換函式轉換成了xml字串來表示。假設上面的方法不存在,或者上面的方法被不正確的複寫,那麼很可能就出現外部JavaScript無法調用到Flash對外註冊的介面。
執行個體如下:
| 1 2 3 4 5 6 7 8 |
<script type= "text/javascript" > var myArg = []; myArg[10000] = 1; myArg[10001] = { a : 1, b : "string" }; </script> |
會被轉換成(最佳化後的):
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
< invoke name = "test" returntype = "javascript" > < arguments > < array > < property id = "10000" > < number >1</ number > </ property > < property id = "10001" > < object > < property id = "a" > < number >1</ number > </ property > < property id = "b" > < string >string</ string > </ property > </ object > </ property > </ array > </ arguments > </ invoke > |
JavaScript調用Flash方法回目錄 CallFunction 是Flash Player外掛程式對外公開的調用介面,無論是使用C++還是JavaScript都是從這個介面來調用Flash的方法。__flash__request 將傳入的參數組成最終的請求體(上面XML),然後發送給Flash Player, Flash Player拿到請求體解析後調用相印的方法,並且把請求參數傳入,然後將執行結果返回。
執行個體如下:
| 1 2 3 |
<script type= "text/javascript" > alert(testSwf.test); </script> |
等同如下:
| 1 2 3 4 5 6 7 8 |
<script type= "text/javascript" > var arg = [ 'test' ]; for ( var i=0; i<arguments.length; ++i) { arg.push(arguments[i]); } testSwf.CallFunction(__flash__request.apply( null , arg)); </script><BR><BR> |
Flash調用JavaScript方法
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var myJavaScript:XML = <script> <![CDATA[ function () { function sum(a, b) { alert(a + b); } sum( 1 , 2 ); } ]]> </script> ExternalInterface.call(myJavaScript); //output 3<BR><BR> |
甚至還可以注入JavaScript代碼:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var myJavaScript:XML = <script> <![CDATA[ function () { window.sum = function (a, b) { alert(a + b); } sum( 1 , 2 ); } ]]> </script> ExternalInterface.call(myJavaScript);<BR><BR> |
之後就可以執行如下調用:
| 1 2 3 |
<script type= "text/javascript" > alert(window.sum); </script> |
這樣甚至能把你的JavaScript代碼嵌入到Flash當中,這樣做法的優劣暫時不進行討論。然而Flash不僅僅能在瀏覽器中調用JavaScript方法或者注入JavaScript代碼,在IE甚至能夠調用和注入VBScript的方法和代碼。
方法的效能最佳化回目錄
之前提到,Flash Player會在SWF成功載入後將6個函數拋到全域上,然而不幸的是,這六個全域函數都不同程度的存在效能問題,其中問題比較嚴重的函數是:
函數之一:__flash__arrayToXML 負責將數群組轉換成XML
| 1 2 3 4 5 6 7 8 9 |
function __flash__arrayToXML(obj) { var s = "<array>" ; for ( var i=0; i<obj.length; i++) { s += " <property id=\"" + i + "\">" + __flash__toXML(obj[i]) + "</property>" ; } return s+ "</array>" ; } |
假設將如下的JavaScript數群組轉換成XML
| 1 2 |
var myArray = []; myArray[10000] = 1; |
上面的函數會迴圈10000次,把所有的數組元素不管存在與否都解析成XML, 這就導致了以下問題:
把效能浪費在無用的解析上 使得XML請求體無比龐大 Flash Player拿到XML資料後還要無奈地建立XML DOM並且將剛才的無用資料解析還原 對字串使用了 += 操作,這個操作在IE瀏覽器的效率非常低
函數之二:__flash__escapeXML 負責將特殊字元轉為實體