先来段简单的代码:
function jsdemo()
{
var doc = window.document;
var div = doc.createelement("div");
div.innerhtml = "hello! this box is created by javascript!";
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函数变量的传递就要麻烦些。因为其中涉及到闭包等问题,所以仅仅传递函数字符串是肯定行不通的。解决这个办法,需要和存储对象类型一个办法:发送方在传递函数前先储存起来,传递的只是一个序列号;接收方收到序列号后,新建一个代理函数,里面包含了这个序列号。当以后被调用时,代理函数将序列号作为参数通知给对方,对方通过序列号从数组里取出原函数,执行。
这样一个大致的轮廓就出来了:
目前一些常用功能可以正常运行。下面写了几个简单的jsdemo,能在actionscript正常运行:
http://www.etherdream.com/funnyscript/runjs/runjs.html
不要忘了,这些js可是运行在actionscript环境下的!
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 = "
" + str + "
"
doc.body.appendchild(div);
}
function jsdemo1()
{
var doc = window.document;
var div = doc.createelement("div");
div.innerhtml = "hello! this box is created by actionscript!";
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; ivar 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,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/