继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

【探索】用ActionScript模拟运行JavaScript

jeck猫
关注TA
已关注
手记 298
粉丝 74
获赞 402

  先来段简单的代码:

function JSDemo()
{
    var doc = window.document;
    var div = doc.createElement("div");
    
    div.innerHTML = "Hello! <i>This box is created by JavaScript!</i>";
    
    div.style.background = "#CCC";
    div.style.font = "bolder 18px 'Courier New'";
    div.style.border = "1px dashed #693";
    
    doc.body.appendChild(div);
}


  这是再简单不过的JS代码,最基本的DOM创建和操作。不过把他复制到ActionScript里,它还能运行吗?显然不可能。虽然他们有着相似语法,但运行环境完全不同,当然是连编译都通不过的。

  

  仔细思考下,AS3虽然是JavaScript2.0的风格,但也向下兼容当前的JS语法。仅语法上说,JS复制到AS下是没有语法错误的,只是变量没有定义类型的提示的警告。但Flash SDK没有提供Web的接口,所以window,document这些变量就不存在了,因此无法通过编译。显然,如果我们能够提供这些接口,那么代码至少能通过编译。

  

  纵观Web下的各种接口,都是从window对象延伸开来。所以我们只需模拟出window对象,之后其他对象就可以从这个顶级接口中获取。由于不同浏览器下的接口都各不相同,并且错综复杂,所以手工的去模拟每一个接口的功能是不现实的。因此我们需要一个AS和Web之间的代理程序,实现接口的自动转换。

  

  ActionScript自带一个功能强大的类: flash.utils.Proxy。继承它之后,我们的类就可以实现一些底层的操作。我们可以覆盖对象默认的属性读写,方法调用等等,类似C++的operator操作符。通过ExternalInterface.call,我们可以向Flash所在Web页面进行交互,并返回数据,于是我们就可以实现AS/JS接口自动化代理了。

   

  例如,当访问window对象的document属性时,我们的getProperty重载函数向Web发送“ 获取window的document属性”指令。Web端的JS收到指令后,将document属性从window对象读取。不过由于document也是个对象,不是基本类型,所以不能直接返回给AS,而是将其储存在数组里,返回给AS一个对象序列号,这个字符串里包含了数组的id位置。当以后访问document的属性时,这个代表document对象的序列号就会传递过去,js就能从数组里还原这个对象。

  

  不过要实现JS/AS函数变量的传递就要麻烦些。因为其中涉及到闭包等问题,所以仅仅传递函数字符串是肯定行不通的。解决这个办法,需要和存储对象类型一个办法:发送方在传递函数前先储存起来,传递的只是一个序列号;接收方收到序列号后,新建一个代理函数,里面包含了这个序列号。当以后被调用时,代理函数将序列号作为参数通知给对方,对方通过序列号从数组里取出原函数,执行。

  

  这样一个大致的轮廓就出来了:

复制代码

package
{
    import flash.display.*;
    

    public class RunJS extends Sprite
    {
        private var window:JSEnv = JSEnv.$;
        

        public function RunJS()
        {
            JSLine("DOM Demo:");
            JSDemo1();
            
            JSLine("Event Demo:");
            JSDemo2();
            
            JSLine("Closure Demo:");
            JSDemo3();
            
            JSLine("AJAX Demo:");
            JSDemo4();
        }
        
        
        function JSLine(str)
        {
            var doc = window.document;
            var div = doc.createElement("div");
            
            div.innerHTML = "<p>" + str + "<hr/></p>"
            doc.body.appendChild(div);
        }
        
        
        function JSDemo1()
        {
            var doc = window.document;
            var div = doc.createElement("div");
            
            div.innerHTML = "Hello! <i>This box is created by ActionScript!</i>";
            
            div.style.background = "#CCC";
            div.style.font = "bolder 18px 'Courier New'";
            div.style.border = "1px dashed #693";
            
            doc.body.appendChild(div);
        }
        
        
        function JSDemo2()
        {
            var doc = window.document;
            var btn = doc.createElement("button");
            
            btn.innerHTML = "Click Me!";
            btn.onclick = function()
            {
                var i = 0;
                window.setInterval(function()
                {
                    btn.innerHTML = "Run in ActionScript: i=" + i++;
                }, 10)
            };
            
            doc.body.appendChild(btn);
        }
        
        
        function JSDemo3()
        {
            var doc = window.document;
            
            for(var i=0; i<5; i++)
            {
                var btn = doc.createElement("button");
                doc.body.appendChild(btn);
                
                btn.innerHTML = "Button" + i;
                btn.onclick = (function(i)
                {
                    return function(){window.alert(i)};
                })(i);
            }
        }
        
        function JSDemo4()
        {
            var doc = window.document;
            var btn = doc.createElement("button");
            
            doc.body.appendChild(btn);
    
            btn.innerHTML = "Load Test.xml";

            btn.onclick = function()
            {
                var xhr = window.ActiveXObject?
                    new window.ActiveXObject("Microsoft.XMLHTTP"):
                    new window.XMLHttpRequest;
                
                xhr.onreadystatechange = function()
                {
                    if(xhr.readyState != 4)
                        return;
                    
                    window.alert(xhr.responseText);
                };

                xhr.open("GET", "Test.xml", true);
                xhr.send();
            };
        }
    }
}


   当然,目前仍有不少问题有待解决。这里将继续研究,借用ActionScript强大的IDE来调试JavaScript。并且升级之前的JS解释器,将ActionScript解释成更高效的JS。从而彻底抛弃混乱纠结的JS-OOP。有兴趣的继续关注。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP

热门评论

大神。这年头你还在写as3啊。。牛逼啊。

查看全部评论