??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久久亚洲AV无码永不,亚洲另类自拍丝袜第1页,亚洲精品视频久久久http://m.tkk7.com/BaSaRa/category/11655.htmlzh-cnTue, 27 Feb 2007 15:01:20 GMTTue, 27 Feb 2007 15:01:20 GMT60好久没更CQ今天查了一下在Firefox下解决Event传递的ҎQ不?/title><link>http://m.tkk7.com/BaSaRa/archive/2006/06/28/55538.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Wed, 28 Jun 2006 06:35:00 GMT</pubDate><guid>http://m.tkk7.com/BaSaRa/archive/2006/06/28/55538.html</guid><wfw:comment>http://m.tkk7.com/BaSaRa/comments/55538.html</wfw:comment><comments>http://m.tkk7.com/BaSaRa/archive/2006/06/28/55538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/BaSaRa/comments/commentRss/55538.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/BaSaRa/services/trackbacks/55538.html</trackback:ping><description><![CDATA[ <font color="#000000">地址Q?a >http://blog.joycode.com/lostinet/archive/2005/02/27/44999.aspx</a><br /><br />我佛׃h的不错:<br />用了try...catch因ؓ在IE下会报错但对面没有影响<br /><br />try { // 让firefox下的event调用像IE下的一?br /> window.constructor.prototype.__defineGetter__("event", function(){ <br /> var o = arguments.callee.caller; <br /> var e; <br /> while(o != null){<br />  e = o.arguments[0]; <br />  if(e && (e.constructor == Event || e.constructor == MouseEvent)) return e; <br />  o = o.caller; <br /> } <br /> return null; <br />}); <br />}catch(e) {}<br /><br />用了q段函数则可以直接写 event(window.event) 来操作event(Event)对象了,很方?br /><br />如果要操作document的事Ӟ好象q个函数无效吧,所以我q样?br /> window.document.onkeyup = function(e) {<br />  var ev = e||window.event;<br />  if (ev.keyCode==27 && dojo.style.getStyle(dojo.widget.byId('detailDiv').domNode, "display")!="none")<br />   dojo.widget.byId('detailDiv').domNode.style.display = "none";<br /> };</font> <img src ="http://m.tkk7.com/BaSaRa/aggbug/55538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-28 14:35 <a href="http://m.tkk7.com/BaSaRa/archive/2006/06/28/55538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]如何优化JavaScript脚本的性能 http://m.tkk7.com/BaSaRa/archive/2006/06/15/52904.htmlBaSaRa BaSaRa Thu, 15 Jun 2006 01:13:00 GMThttp://m.tkk7.com/BaSaRa/archive/2006/06/15/52904.htmlhttp://m.tkk7.com/BaSaRa/comments/52904.htmlhttp://m.tkk7.com/BaSaRa/archive/2006/06/15/52904.html#Feedback0http://m.tkk7.com/BaSaRa/comments/commentRss/52904.htmlhttp://m.tkk7.com/BaSaRa/services/trackbacks/52904.html

作者:ShiningRay @ Nirvana Studio

随着|络的发展,|速和机器速度的提高,来多的网站用C丰富客户端技术。而现在Ajax则是最为流行的一U方式。JavaScript是一U解释型语言Q所以能无法辑ֈ和C/Java之类的水qI限制了它能在客户端所做的事情Qؓ了能改进他的性能Q我惛_于我以前lJavaScript做过的很多测试来谈谈自己的经验,希望能帮助大家改q自qJavaScript脚本性能?/p>

语言层次斚w

循环

循环是很常用的一个控制结构,大部分东西要依靠它来完成Q在JavaScript中,我们可以使用for(;;),while(),for(in)三种循环Q事实上Q这三种循环中for(in)的效率极差,因ؓ他需要查询散列键Q只要可以就应该量用。for(;;)和while循环的性能应该说基本(qx使用Ӟ{h?/p>

而事实上Q如何用这两个循环Q则有很大讲I。我在测试中有些很有意思的情况Q见附录。最后得出的l论是:

  • 如果是@环变量递增或递减Q不要单独对循环变量赋|应该在它最后一ơ读取的时候用嵌套的++?mdash;操作W?/p>

  • 如果要与数组的长度作比较Q应该事先把数组的length属性放入一个局部变量中Q减查询次数?/p>

局部变量和全局变量

局部变量的速度要比全局变量的访问速度更快Q因为全局变量其实是全局对象的成员,而局部变量是攑֜函数的栈当中的?/p>

不用Eval

使用eval相当于在q行时再ơ调用解释引擎对内容q行q行Q需要消耗大量时间。这时候用JavaScript所支持的闭包可以实现函数模版(关于闭包的内容请参考函数式~程的有兛_容)

减少对象查找

因ؓJavaScript的解释性,所以a.b.c.d.eQ需要进行至?ơ查询操作,先检查a再检查a中的bQ再查b中的cQ如此往下。所以如果这L表达式重复出玎ͼ只要可能Q应该尽量少出现q样的表辑ּQ可以利用局部变量,把它攑օ一个时的地方q行查询?/p>

q一点可以和循环l合hQ因为我们常常要Ҏ字符丌Ӏ数l的长度q行循环Q而通常q个长度是不变的Q比如每ơ查询a.lengthQ就要额外进行一个操作,而预先把var len=a.lengthQ则少了一ơ查询?/p>

字符串连?/h2>

如果是追加字W串Q最好用s+=anotherStr操作Q而不是要使用s=s+anotherStr?/p>

如果要连接多个字W串Q应该少使用+=Q如

s+=a;
s+=b;
s+=c;

应该写成

s+=a + b + cQ?/pre>

而如果是攉字符Ԍ比如多次对同一个字W串q行+=操作的话Q最好用一个缓存。怎么用呢Q用JavaScript数组来收集,最后用joinҎq接hQ如?/p>

var buf = new Array();
for(var i = 0; i < 100; i++){
buf.push(i.toString());
}
var all = buf.join("");

cd转换

cd转换是大家常犯的错误Q因为JavaScript是动态类型语aQ你不能指定变量的类型?/p>

1. 把数字{换成字符Ԍ应用"" + 1Q虽然看h比较丑一点,但事实上q个效率是最高的Q性能上来_

("" +) > String() > .toString() > new String()

q条其实和下面的“直接?rdquo;有点cMQ尽量用编译时p使用的内部操作要比运行时使用的用h作要快?/p>

String()属于内部函数Q所以速度很快Q?toString()要查询原型中的函敎ͼ所以速度逊色一些,new String()用于q回一个精的副本?/p>

2. 点数{换成整型Q这个更Ҏ出错Q很多h喜欢使用parseInt()Q其实parseInt()是用于将字符串{换成数字Q而不是QҎ和整型之间的转换Q我们应该用Math.floor()或者Math.round()?/p>

另外Q和W二节的对象查找中的问题不一PMath是内部对象,所以Math.floor()其实q没有多查询方法和调用的时_速度是最快的?/p>

3. 对于自定义的对象Q如果定义了toString()Ҏ来进行类型{换的话,推荐昑ּ调用toString()Q因为内部的操作在尝试所有可能性之后,会尝试对象的toString()Ҏ试能否转化为StringQ所以直接调用这个方法效率会更高

使用直接?/h2>

其实q个影响倒比较小Q可以忽略。什么叫使用直接量,比如QJavaScript支持使用[param,param,param,...]来直接表达一个数l,以往我们都用new Array(param,param,...)Q用前者是引擎直接解释的,后者要调用一个Array内部构造器Q所以要略微快一点点?/p>

同样Qvar foo = {}的方式也比var foo = new Object();快,var reg = /../;要比var reg=new RegExp()快?/p>

字符串遍历操?/h2>

对字W串q行循环操作Q譬如替换、查找,应用正则表辑ּQ因为本wJavaScript的@环速度比较慢Q而正则表辑ּ的操作是用C写成的语a的APIQ性能很好?/p>

高对象

自定义高U对象和Date、RegExp对象在构造时都会消耗大量时间。如果可以复用,应采用缓存的方式?/p>

DOM相关

插入HTML

很多人喜Ƣ在JavaScript中用document.write来给面生成内容。事实上q样的效率较低,如果需要直接插入HTMLQ可以找一个容器元素,比如指定一个div或者spanQƈ讄他们的innerHTML来将自己的HTML代码插入到页面中?/p>

对象查询

使用[“”]查询要比.items()更快Q这和前面的减少对象查找的思\是一LQ调?items()增加了一ơ查询和函数的调用?/p>

创徏DOM节点

通常我们可能会用字W串直接写HTML来创点,其实q样?/p>

  1. 无法保证代码的有效?/p>

  2. 字符串操作效率低

所以应该是用document.createElement()ҎQ而如果文中存在现成的样板节点,应该是用cloneNode()ҎQ因Z用createElement()Ҏ之后Q你需要设|多ơ元素的属性,使用cloneNode()则可以减属性的讄ơ数——同样如果需要创建很多元素,应该先准备一个样板节炏V?/p>

定时?/h2>

如果针对的是不断q行的代码,不应该用setTimeoutQ而应该是用setInterval。setTimeout每次要重新设|一个定时器?/p>

其他

脚本引擎

据我试Microsoft的JScript的效率较Mozilla的Spidermonkey要差很多Q无论是执行速度q是内存理上,因ؓJScript现在基本也不更新了。但SpiderMonkey不能使用ActiveXObject

文g优化

文g优化也是一个很有效的手D,删除所有的I格和注释,把代码放入一行内Q可以加快下载的速度Q注意,是下载的速度而不是解析的速度Q如果是本地Q注释和I格q不会媄响解释和执行速度?/p>

ȝ

本文ȝ了我在JavaScript~程中所扑ֈ的提高JavaScriptq行性能的一些方法,其实q些l验都基于几条原则:

  1. 直接拿手头现成的东西比较快,如局部变量比全局变量快,直接量比q行时构造对象快{等?/p>

  2. 可能少地减执行次敎ͼ比如先缓存需要多ơ查询的?/p>

  3. 可能用语a内置的功能,比如串链接?/p>

  4. 可能用系l提供的APIQ因些API是编译好的二q制代码Q执行效率很?/p>

同时Q一些基本的法上的优化Q同样可以用在JavaScript中,比如q算l构的调_q里׃再赘qC。但是由于JavaScript是解释型的,一般不会在q行时对字节码进行优化,所以这些优化仍然是很重要的?/p>

当然Q其实这里的一些技巧同样用在其他的一些解释型语言中,大家也可以进行参考?/p>

参?/h1>

附录1

׃是以前做q的试Q测试代码已l不全,我补充了一部分如下Q?/p>

var print;
if(typeof document != "undefined" ){
print = function(){
document.write(arguments[0]);
}
}else if(typeof WScript != "undefined" ){
print = function(){
WScript.Echo(arguments[0],arguments[1],arguments[2]);
}
}
function empty(){
}
function benchmark(f){
var i = 0;
var start = (new Date()).getTime();
while(i < pressure){
f(i++);
}
var end = (new Date()).getTime();
WScript.Echo(end-start);
}
/*
i=0
start = (new Date()).getTime();
while(i < 60000){
c = [i,i,i,i,i,i,i,i,i,i];
i++;
}
end = (new Date()).getTime();
WScript.Echo(end-start);
i=0
start = (new Date()).getTime();
while(i < 60000){
c = new Array(i,i,i,i,i,i,i,i,i,i);
i++;
}
var end = (new Date()).getTime();
WScript.Echo(end-start);
*/
function internCast(i){
return "" + i;
}
function StringCast(i){
return String(i)
}
function newStringCast(i){
return new String(i)
}
function toStringCast(i){
return i.toString();
}
function ParseInt(){
return parseInt(j);
}
function MathFloor(){
return Math.floor(j);
}
function Floor(){
return floor(j);
}
var pressure = 50000;
var a  = "";
var floor = Math.floor;
j = 123.123;
print("-------------\nString Conversion Test");
print("The empty:", benchmark(empty));
print("intern:", benchmark(internCast));
print("String:");
benchmark(StringCast);
print("new String:");
benchmark(newStringCast);
print("toString:");
benchmark(toStringCast);
print("-------------\nFloat to Int Conversion Test");
print("parseInt");
benchmark(ParseInt);
print("Math.floor");
benchmark(MathFloor);
print("floor")
benchmark(Floor);
function newObject(){
return new Object();
}
function internObject(){
return {};
}
print("------------\nliteral Test");
print("runtime new object", benchmark(newObject));
print("literal object", benchmark(internObject));

附录2

代码1Q?/p>

    for(var i=0;i<100;i++){
arr[i]=0;
}


代码2Q?/p>

    var i = 0;
while(i < 100){
arr[i++]=0;
}


代码3Q?/p>

    var i = 0;
while(i < 100){
arr[i]=0;
i++;
}


在firefox下测试这两段代码Q结果是代码2优于代码1?Q而代?一般优于代?Q有时会被代?过Q而在IE 6.0下,试压力较大的时候(如测?0000ơ以上)代码2?则有时候优于代?Q有时候就会远q落后代?Q而在试压力较小Q如5000ơ)Q则代码2>代码3>代码1?/p>

代码4Q?/p>

    var i = 0;
var a;
while(i < 100){
a = 0;
i++;
}


代码5Q?/p>

    var a;
for(var i=0;i<100;i++){
a = 0;
}

上面两段代码在Firefox和IE下测试结果都是性能接近的?/p>

代码6Q?/p>

    var a;
var i=0;
while(i<100){
a=i;
i++;
}


代码7Q?/p>

    var a;
var i=0;
while(i<100){
a=i++;
}


代码8Q?/p>

    var a;
for(var i=0;i<100;i++){
a = i;
}


代码9Q?/p>

    var a;
for(var i=0;i<100;){
a = i++;
}

q四D代码在Firefox??的性能接近Q??的性能接近Q?, 8 < 7, 9Q?/p>

最后我们来看一下空循环

代码10Q?/p>

    for(var i=0;i<100;i++){   }


代码11Q?/p>

    var i;
while(i<100){        i++;    }

最后的试出现了神奇的l果QFirefox下代?0所q旉与代?1所q大约?4:1。所以它不具备参考h|于是我没有放在一开始给大家看?/p>



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=747880



BaSaRa 2006-06-15 09:13 发表评论
]]>
[转] JavaScript 2 已经定发布日期 http://m.tkk7.com/BaSaRa/archive/2006/06/15/52896.htmlBaSaRa BaSaRa Thu, 15 Jun 2006 00:53:00 GMThttp://m.tkk7.com/BaSaRa/archive/2006/06/15/52896.htmlhttp://m.tkk7.com/BaSaRa/comments/52896.htmlhttp://m.tkk7.com/BaSaRa/archive/2006/06/15/52896.html#Feedback0http://m.tkk7.com/BaSaRa/comments/commentRss/52896.htmlhttp://m.tkk7.com/BaSaRa/services/trackbacks/52896.html  ҎBrendan Eich的演讲稿QFireFox的未来版本将逐步加入以ECMAScript Edtion 4本的JavaScript 2的支持,?007q第二季度,FireFox 3包含基本完整的JavaScript 2?br />
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=753266


BaSaRa 2006-06-15 08:53 发表评论
]]>
[引用] 寚w包的理解http://m.tkk7.com/BaSaRa/archive/2006/06/13/52377.htmlBaSaRa BaSaRa Tue, 13 Jun 2006 03:13:00 GMThttp://m.tkk7.com/BaSaRa/archive/2006/06/13/52377.htmlhttp://m.tkk7.com/BaSaRa/comments/52377.htmlhttp://m.tkk7.com/BaSaRa/archive/2006/06/13/52377.html#Feedback0http://m.tkk7.com/BaSaRa/comments/commentRss/52377.htmlhttp://m.tkk7.com/BaSaRa/services/trackbacks/52377.html今天在群里面瞎谈Q就谈到“闭包”上来了,何种语言支持闭包Q自己g下吧Q其中JavaScript是支持闭包概늚一U语a/脚本(?)。以下是我对他的见解(以javascript举例)?br />
先了解下在一个对象内如何声明变量Q一下以Test对象ZQ?br />Public变量Q?br />
function Test()
{
    
this.x = 1;
}
或?
Test.prototype.x = 1;
公共变量而言之,外界对象可以对公共变量访问,q且公共变量可以在对象的构造函C声明外,q可以在对象的prototype成员中声明。换句话_你可以在M时候添加公共变量(利用prototypeQ。prototype是一个特别的成员变量Qjs是利用q个成员变量的特性来实现l承的。当一个成员被索且没有在对象中发现的时候,那么它就会从对象构造器的prototype成员中获取他。如果要从外界调用这个对象的ҎQ或者是通过q个Ҏ操作q个对象里面的所有成员,你可以通过prototype加入Q?br />
Test.prototype.Plus = function () {}

Private变量Q?
function Test()
{
    
var self = this;
    
    
var x = 1;
    
    
function Plus1() {}
    
    
var pPlus = function Plus2() {}
}
U有的变量只能由成员的私有方法或者是ҎҎQPrivilegedQ下面讲刎ͼ讉KQ需要注意的是,上面的Plus1()q个Ҏ和pPlus()q个Ҏ是一LQ只是声明的方式不通而已Q他们都是私有方法,他和Ҏ变量的声明方法很怼Q只是少了个this多了个varQ但是他们是不同的,应该特别注意。另外一ҎQ私有变量是在无法被外界讉K的同Ӟ他也不能由对象的公共Ҏ讉K。私有方法只是在构造函数内的内部方法。私有变量只能在构造函C声明?br />
Privileged变量Q?br />
function Test()
{
    
this.pPlus = function () {}
}
什么叫PrivilegedQ特权)变量呢?ҎҎ可以讉KU有Ҏ和私有变量,同时他对外界是可见的。你可以重新声明q个U有Ҏ或者是删除他(重新对这个特权方法赋|nullDC删除)Q但是不能改变他。特权变量也只能在构造函C声明?br />
好了Q对象声明介l到q里Q这些声明模式都是由js的closureQ闭包)Ҏ所支持的,下面介绍闭包?br />
在一个闭包内Q你可以暂且(?)理解成在构造函数内Q内部函数L可以讉K函数外部的变量和参数的。就在内部函数return后,闭包内的所有变量都会被保存hQ就好像一个上下文一栗下面我以一个例子说明这个问题,例子来源在群内,由YOK提供Q例子已l被修改Q只是用来简单说明问题)?br />
说明Q按test按钮输出相加的|期望gؓ3?
<html>
    
<body>
        
<input type="button" id="test" value="test" />
        
<script>
function Test (x, y)
{
    
var x = x;
    
var y = y;
}
Test.prototype.add 
= function ()
{
    alert(
this.x + this.y);
}

var t = new Test(12);
document.getElementById('test').onclick 
= t.add;
        
</script>
    
</body>
</html>

q行例子Q但是输?quot;NaN"。这是什么问题呢Q我最初调试的时候,以ؓ是this的问题,我原本理解成在addҎ中this是指向test按钮Q其实this指向window对象Q,而他不包含x和y的两个变量,所以输出错误。首先,q个理解是正的Q但是你要如何修Ҏ能获取正的l果呢。我们已l知道,在Test构造函CQ我们声明的xQy是两个私有变量,你不可能在外部访问到Q所以必d觅他路。我们利用特权变量来解决?
<html>
    
<body>
        
<input type="button" id="test" value="test" NAME="test"/>
        
<script>
function Test (x, y)
{
    
var x = x;
    
var y = y;
    
    
this.add = function ()    // Ҏ变量Q可以访问私有变量,又对外公开
    {
        alert(x 
+ y);
    }
}

var t = new Test(12);
document.getElementById('test').onclick 
= t.add;
        
</script>
    
</body>
</html>

上面呈现的是闭包的其中一个特性,下面用来说他的另外一个特性?
<html>
    
<body>
        
<input type="button" id="test" value="test" NAME="test"/>
        
<script>
function Test ()
{
    
var z = 1;
    
    
this.add = function ()
    {
        alert(z
++);
    }
}

var t = new Test();
document.getElementById('test').onclick 
= t.add;
        
</script>
    
</body>
</html>
每次输出Q值都会增?Q说明闭包内上下文就addҎreturn后都会被保存?br />
最后说下怎么动态替换行为(q里是按钮click的行为)?br />
<html>
    
<body>
        
<input type="button" id="test" value="test" NAME="test"/>
        
<script>
function Test ()
{
    
var z = 1;
    
var self = this;
    
var pBtn = null;
    
    
this.selfSubtract = function ()
    {
        z
--;z--;
        alert(z);
        pBtn.onclick 
= self.selfPlus;
    }
    
    
this.selfPlus = function ()
    {
        z
++;
        alert(z);
        pBtn.onclick 
= self.selfSubtract;
    }
    
    
this.getFunction = function (btn)
    {
        pBtn 
= btn;
        
return self.selfSubtract;
    }
}

var t = new Test();
var btn = document.getElementById('test');
btn.onclick 
= t.getFunction(btn);
        
</script>
    
</body>
</html>
以上是我对他的一点见解,closure是js的一个特性而已Q我们可以利用这个特性设计更灵z,其他语言Q我google到的好像叫LuaQ不知道他是什么,他也支持。由于对js了解不深Q请高手斧正,enjoy it~~~ :)

BaSaRa 2006-06-13 11:13 发表评论
]]>
兼容IE和Firefox的数据岛Ҏhttp://m.tkk7.com/BaSaRa/archive/2006/06/09/51710.htmlBaSaRa BaSaRa Fri, 09 Jun 2006 07:53:00 GMThttp://m.tkk7.com/BaSaRa/archive/2006/06/09/51710.htmlhttp://m.tkk7.com/BaSaRa/comments/51710.htmlhttp://m.tkk7.com/BaSaRa/archive/2006/06/09/51710.html#Feedback0http://m.tkk7.com/BaSaRa/comments/commentRss/51710.htmlhttp://m.tkk7.com/BaSaRa/services/trackbacks/51710.html看我们老大的代码,不错Q特地奉献出?br />
首先QHTML面Q?br /><script type="text/javascript" src="xmlPathDemo.js"></script>
<h2>XML Order Database</h2>
<form>
 <table border="0">
  <tr>
   <td>SKU</td>
   <td><input type="text" name="SKU"></td>
  </tr>
  <tr>
   <td>Price</td>
   <td><input type="text" name="Price"></td>
  </tr>
  <tr>
   <td>Quantity</td>
   <td><input type="text" name="Quantity"></td>
  </tr>
  <tr>
   <td>Total</td>
   <td><input type="text" name="Total"></td>
  </tr>
  <tr>
   <td>Description</td>
   <td><input type="text" name="Description"></td>
  </tr>
 </table>
 <input type="button" value=" << " onClick="getDataPrev();">
 <input type="button" value=" >> " onClick="getDataNext();">
</form>

其次Q一个XML数据源:
<?xml version="1.0" ?>
<Order>
 <Account>9900234</Account>
 <Item id="1">
  <SKU>1234</SKU>
  <PricePer>5.95</PricePer>
  <Quantity>100</Quantity>
  <Subtotal>595.00</Subtotal>
  <Description>Super Widget Clamp</Description>
 </Item>
 <Item id="2">
  <SKU>6234</SKU>
  <PricePer>22.00</PricePer>
  <Quantity>10</Quantity>
  <Subtotal>220.00</Subtotal>
  <Description>Mighty Foobar Flange</Description>
 </Item>
 <Item id="3">
  <SKU>9982</SKU>
  <PricePer>2.50</PricePer>
  <Quantity>1000</Quantity>
  <Subtotal>2500.00</Subtotal>
  <Description>Deluxe Doohickie</Description>
 </Item>
 <Item id="4">
  <SKU>3256</SKU>
  <PricePer>389.00</PricePer>
  <Quantity>1</Quantity>
  <Subtotal>389.00</Subtotal>
  <Description>Muckalucket Bucket</Description>
 </Item>
 <NumberItems>1111</NumberItems>
 <Total>3704.00</Total>
 <OrderDate>07/07/2002</OrderDate>
 <OrderNumber>8876</OrderNumber>
</Order>

引用q个JSQ?br />try{
 var i = -1;
 var orderDoc = new ActiveXObject("MSXML2.DOMDocument.3.0");
 orderDoc.load("order.xml");
 var items = orderDoc.selectNodes("/Order/Item");
}catch(e){}

function getNode(doc, xpath) {
 varretval = "";
 var value = doc.selectSingleNode(xpath);
 if (value) retval = value.text;
 return retval;
}

function getDataNext() {
 i++;
 if (i > items.length - 1) i = 0;
 
 document.forms[0].SKU.value = getNode(orderDoc, "/Order/Item[" + i + "]/SKU");
 document.forms[0].Price.value = getNode(orderDoc, "/Order/Item[" + i + "]/PricePer");
 document.forms[0].Quantity.value = getNode(orderDoc, "/Order/Item[" + i + "]/Quantity");
 document.forms[0].Total.value = getNode(orderDoc,"/Order/Item[" + i + "]/Subtotal");
 document.forms[0].Description.value = getNode(orderDoc, "/Order/Item[" + i + "]/Description");
}

function getDataPrev() {
 i--;
 if (i < 0) i = items.length - 1;
 
 document.forms[0].SKU.value = getNode(orderDoc, "/Order/Item[" + i + "]/SKU");
 document.forms[0].Price.value = getNode(orderDoc,"/Order/Item[" + i + "]/PricePer");
 document.forms[0].Quantity.value = getNode(orderDoc, "/Order/Item[" + i + "]/Quantity");
 document.forms[0].Total.value = getNode(orderDoc,"/Order/Item["+ i + "]/Subtotal");
 document.forms[0].Description.value = getNode(orderDoc, "/Order/Item[" + i + "]/Description");
}  

window.onload = function() {
 getDataNext();
}

好了Q运行看看,和IE的数据岛功能一?/font>



BaSaRa 2006-06-09 15:53 发表评论
]]>
文摘Q《JavaScriptQ世界上最被误解的语言?/title><link>http://m.tkk7.com/BaSaRa/archive/2006/06/09/51702.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Fri, 09 Jun 2006 07:42:00 GMT</pubDate><guid>http://m.tkk7.com/BaSaRa/archive/2006/06/09/51702.html</guid><wfw:comment>http://m.tkk7.com/BaSaRa/comments/51702.html</wfw:comment><comments>http://m.tkk7.com/BaSaRa/archive/2006/06/09/51702.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/BaSaRa/comments/commentRss/51702.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/BaSaRa/services/trackbacks/51702.html</trackback:ping><description><![CDATA[<p>  JavaScript, 亦称?Mocha 、LiveScriptQ也叫做 JScript ECMAScript Q是世界上流行的~程语言之一。事实上世界上差不多每台个h电脑都至安装了一个JavaScript解释器。JavaScript的流行完全在于它作ؓWWW的脚本语a的角艌Ӏ?</p> <p>  不管它有多么行Q极有Z解JavaScript是一个十分动态的通用面向对象~程语言。这怎能成ؓ一个秘密呢Qؓ什么这个语a如此被误解? </p> <p> </p> <p><font size="2"><strong>关于名字</strong></font></p> <p><font size="2"><br /></font>  q个Java-前缀暗示了JavaScript和Java的关p,也就是JavaScipt是Java的一个子集也是不如Java强大。看上去q个名称故意制造؜乱,然后随之而来的是误解。JavaScriptq不是解释型的Java语言。Java是解释型的JavaQJavaScript是另一U语a?</p> <p>  JavaScript和Java的语法很怼Q就象Java和C的语法相g栗但它也不是Java的子集就像Java也不是C的子集一栗在应用上,Java要远比原先设想的好得多(Java原称OakQ?</p> <p>  JavaScriptq不是由Sun公司──Java的老家──开发的。JavaScript是由Netscape公司开发。它本来叫做LiveScriptQ这个名字倒ƈ不是那样Ҏh?</p> <p>  q个-Script 后缀暗示了它g不是一个完整的~程语言──大多Ch以ؓ脚本语言׃真正的~程语言。但其实q是一个专长的问题。相对C而言QJavaScript牺牲了性能但带来更强的表达力和动态性?/p> <p> </p> <p><font size="2"><strong>披着C外衣的Lisp</strong></font></p> <p><strong><font size="2"></font></strong><br />  JavaScript的C风格的语法,包括大括号和复杂的for 语句Q让它看h好象是一个普通的q程式语a。这是一个误|而事实上JavaScript和函数式语言如Lisp和Scheme有更多的共同之处。它用数l代替了列表Q用对象代替了属性列表,而且函数是第一型的Q同时还有闭包。你不需要Lisp那些括号可以用lambda子?</p> <p> </p> <p><strong><font face="黑体" size="3"><font face="宋体" size="2">思维定势</font></font></strong></p> <p><strong><font face="黑体" size="3"><font face="宋体" size="2"></font><br /></font></strong>  JavaScript是原本只是被设计在Netscape Navigator 中运行的。Netscape的成功让JavaScript成ؓ几乎所有浏览器的标准配|。这D了对JavaScript的思维定势。JavaScript直就是程序语a中的George Reeves Q一位曾扮演h的演员,但后来死于枪杀Q被官方认ؓ自杀Q细节不详──译注Q。而事实上QJavaScript也适合很多和Web无关的应用程序?</p> <p> </p> <p><font size="2"><strong>不断改变的目?/strong></font></p> <p><font size="2"><strong></strong><br /></font>  JavaScript的第一个版本功能十分弱。它~少异常处理、内部函数和l承。而它的现在的形态,它已l是一套完整的面向对象语言。但很多看法都是认ؓ它的形式q不成熟?</p> <p>  理q个语言的ECMA委员正在开发扩展,原意是很好,而这样做却会加剧q个语言本来最严重的问题:版本太多了。这也造成了很多؜乱?</p> <p> </p> <p><strong><font size="2">设计错误</font></strong></p> <p><strong><font size="2"></font></strong><br />  没有什么编E语a是完的QJavaScript当然也有它的设计上的错误Q如+的重载同时表C加和带cd自动转换的串q接Q和有错误們֐?with 语句——应该避免使用。Javascript的保留字{略q于严格。引入分号也是一个很大的错误Q正则表辑ּ的记号也是。这些错误会很容易导致编E错误,q导致语a的设计的全局层面上的问题。幸q的是,q些问题可以用一个很好的lintE序来避免?</p> <p>q个语言的设计从整体上看q是十分健全的。但很o人惊讶的是, ECMAScript委员会好象根本不想修正这些错误。也总们对重新设计一个更感兴?</p> <p> </p> <p><font size="3"><strong><font size="2">肮脏的实?/font></strong></font></p> <p><font size="3"><strong><font size="2"></font><br /></strong></font>JavaScript的早期实现错误百出。这对该语言带来了很恶劣的媄响。更p糕的是Q这些实现还被嵌入的更错误百出的览器中?/p> <p> </p> <p><strong>拙劣的书c?/strong></p> <p><strong></strong><br />  几乎所有的书籍都十分恐怖。里面到处是错误、蹩脚的例子q自创一套拙劣的惯例。语a中重要的Ҏ却常常解释不好Q或者干脆完全不写。我阅了几十本JavaScript的书Q我只推荐两本:JavaScript: The Definitive Guide (4th Edition) by David Flanagan and Dynamic HTML (2nd Edition) by Danny Goodman. 都来自于 O'Reilly. </p> <p> </p> <p><strong>不够标准的标?/strong></p> <p><strong></strong><br />  该语a的官Ҏ准规D明书由ECMA发布。但该规g也是质量奇差。它难以阅读也难以理解。它也对拙劣书籍的问题作Z自己的一?ldquo;贡献”Q因Z者无法用这个标准文来增加他们对语a的认识。ECMA和TC39委员会应该ؓ此感到深q愧?</p> <p> </p> <p><strong>业余爱好?/strong></p> <p><strong></strong><br />大部分写JavaScript的h都不是程序员。他们缺乏训l写好程序的修养。JavaScript有如此丰富的表达能力Q他们可以Q意用它来写代码,以Q何Ş式。这lJavaScript带来了一个名声──它是专门为外行设计的Q不适合专业的程序员。这昄不是事实?</p> <p> </p> <p><strong>面向对象</strong></p> <p><strong></strong><br />  JavaScript是不是面向对象的Q它拥有对象Q可以包含数据和处理数据的方法。对象可以包含其它对象。它没有c,但它却有构造器可以做类能做的事Q包括扮演类变量和方法的容器的角艌Ӏ它没有Zcȝl承Q但它有Z原型的ѝ?</p> <p>  两个建立对象pȝ的方法是通过l承Q是一?hellip;…Q和通过聚合Q有一?hellip;…Q。JavaScript两个都有Q但它的动态性质让它可以在聚合上越?</p> <p>  一些批评说JavaScript不是真正面向对象的因为它不能提供信息的隐藏。也是Q对象不能有U有变量和私有方法:所有的成员都是公共的?</p> <p>  但又有证明了JavaScript对象可以拥有U有变量和私有方法。当Ӟ极少有h认识刎ͼ因ؓJavaScript是世界是最受误解的E序嘛! </p> <p>  另外q有批评说JavaScript不能提供l承Q这里证明了JavaScript不仅能支持传l的l承q能应用其它的代码复用模式?</p> <p> </p> <p>作者:Douglas Crockford</p> <p>译Q?font face="Nimbus Roman No9 L, serif">ShiningRay</font> </p><img src ="http://m.tkk7.com/BaSaRa/aggbug/51702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-09 15:42 <a href="http://m.tkk7.com/BaSaRa/archive/2006/06/09/51702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从ajax.cn摘录下来的ajax设计模式Q其实也是《ajax in action》的W三章主要内容:Q?/title><link>http://m.tkk7.com/BaSaRa/archive/2006/06/09/51605.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Fri, 09 Jun 2006 01:20:00 GMT</pubDate><guid>http://m.tkk7.com/BaSaRa/archive/2006/06/09/51605.html</guid><wfw:comment>http://m.tkk7.com/BaSaRa/comments/51605.html</wfw:comment><comments>http://m.tkk7.com/BaSaRa/archive/2006/06/09/51605.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/BaSaRa/comments/commentRss/51605.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/BaSaRa/services/trackbacks/51605.html</trackback:ping><description><![CDATA[<p>//Facade模式实例<br />var net=new Object();<br />net.READY_STATE_UNINITIALIZED=0;<br />net.READY_STATE_LOADING=1;<br />net.READY_STATE_LOADED=2;<br />net.READY_STATE_INTERACTIVE=3;<br />net.READY_STATE_COMPLETE=4;<br />net.ContentLoader=function(url,onload,onerror){<br />this.url=url;<br />this.req=null;<br />this.onload=onload;<br />this.onerror=(onerror) ? onerror : this.defaultError;<br />this.loadXMLDoc(url);<br />net.ContentLoader.prototype={<br />  loadXMLDoc:function(url){<br />    if (window.XMLHttpRequest){<br />      this.req=new XMLHttpRequest();<br />    } else if (window.ActiveXObject){<br />      this.req=new ActiveXObject("Microsoft.XMLHTTP");<br />    }<br />    if (this.req){<br />      try{<br />        var loader=this;<br />        this.req.onreadystatechange=function(){<br />        loader.onReadyState.call(loader);<br />      }<br />      this.req.open('GET',url,true);<br />      this.req.send(null);<br />      }catch (err){<br />        this.onerror.call(this);<br />      }<br />    }<br />  },<br />  onReadyState:function(){<br />    var req=this.req;<br />    var ready=req.readyState;<br />    if (ready==net.READY_STATE_COMPLETE){<br />      var httpStatus=req.status;<br />      if (httpStatus==200 || httpStatus==0){<br />        this.onload.call(this);<br />      }else{<br />        this.onerror.call(this);<br />      }<br />    }<br />  },<br />  defaultError:function(){<br />    alert("error fetching data!"<br />      +"\n\nreadyState:"+this.req.readyState<br />      +"\nstatus: "+this.req.status<br />      +"\nheaders: "+this.req.getAllResponseHeaders());<br />  }<br />}</p> <p>//Adapter模式实例<br />var xhr = new XMLHttpRequest();<br />xhr.open("GET", "myData.xml");<br />xhr.onreadystatechange = function(){<br />  if(xhr.readyState == 4){<br />    alert(xhr.responseXML);<br />  }<br />}<br />xhr.send(null);</p> <p><br />//Observer模式实例<br />window.onloadListeners=new Array();<br />  window.addOnLoadListener(listener){<br />  window.onloadListeners[window.onloadListeners.length]=listener;<br />}</p> <p>window.onload=function(){<br />  for(var i=0;i<window.onloadListeners.length;i++){<br />    var func=window.onlloadListeners[i];<br />    func.call();<br />  }<br />}</p> <p>//Singleton模式实例<br />var SingletonObj = {<br />  property1: value1,<br />  property2: value2,<br />  ...<br />  method1:function(){<br />    ...<br />  }<br />  method2:function(){<br />    ...<br />  }<br />  ...<br />}</p> <p>function getSingletonObj() {<br />  if(!top.SingletonObj) {<br />    var top.SingletonObj = {<br />      ...<br />    }<br />    top.SingletonObj.init(...);<br />  }<br />  return top.SingletonObj;<br />}</p> <p>//Command模式实例<br />function buttonOnclickHandler(event){<br />  var data=calculate();<br />  showData(dataTable,data);<br />}<br />function ajaxOnloadHandler(){<br />  var data=calculate();<br />  showData(otherDataTable,data);<br />}<br />function calculate(){<br />  var data=new Array();<br />  data[0]=6;<br />  data[1]=data[0]/3;<br />  data[2]=data[0]*data[1]+7;<br />  return data;<br />}<br />function showData(table,data){<br />  var newRow=createTableRow(table);<br />  for (var i=0;i<data.length;i++){<br />    createTableCell(newRow,data[i]);<br />  }<br />}<br />buttonDiv.onclick=buttonOnclickHandler;<br />poller.onload=ajaxOnloadHandler;</p> <p>//MVC应用实例<br />function Button(value,domEl){<br />  this.domEl=domEl;<br />  this.value=value;<br />  this.domEl.buttonObj=this;<br />  this.domEl.onclick=this.clickHandler;<br />}</p> <p>Button.prototype.clickHandler=function(){<br />  var buttonObj=this.buttonObj;<br />  var value=(buttonObj && buttonObj.value) ?<br />    buttonObj.value : "unknown value";<br />  alert(value);<br />}</p><img src ="http://m.tkk7.com/BaSaRa/aggbug/51605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-09 09:20 <a href="http://m.tkk7.com/BaSaRa/archive/2006/06/09/51605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>q几天没I更新BLOGQ今天就放个很简单的解析JSONE序?/title><link>http://m.tkk7.com/BaSaRa/archive/2006/06/08/51383.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Thu, 08 Jun 2006 08:09:00 GMT</pubDate><guid>http://m.tkk7.com/BaSaRa/archive/2006/06/08/51383.html</guid><wfw:comment>http://m.tkk7.com/BaSaRa/comments/51383.html</wfw:comment><comments>http://m.tkk7.com/BaSaRa/archive/2006/06/08/51383.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/BaSaRa/comments/commentRss/51383.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/BaSaRa/services/trackbacks/51383.html</trackback:ping><description><![CDATA[<p>一个JSONQ?br />var infos = {<br /> "user" : {<br />  "id"  : "001",<br />  "data" : [<br />   {"id":"loginName", "value":"yiyi"},<br />   {"id":"name", "value":"翼"},<br />   {"id":"sex", "value":"?quot;}, <br />   {"id":"age", "value":"22"},<br />  ]<br /> }<br />}<br /><br />function parse(v, partion) {<br /> var splits = partion.split(".");<br /> var tmp = v;<br /> for(var i=0;i<splits.length;i++){<br />  tmp = tmp[splits[i]];<br /> }<br /> alert(tmp);<br />}</p> <p>parse(infos, "user.data");<br /><br />只是很简单的深度解析Q开始没q样做,是我们的老大写的 - - 俺太W了<img src="http://m.tkk7.com/Emoticons/msn/sad_smile.gif" alt="" /></p><img src ="http://m.tkk7.com/BaSaRa/aggbug/51383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-08 16:09 <a href="http://m.tkk7.com/BaSaRa/archive/2006/06/08/51383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天整理了一下dojo事g机制Q包括一些例?/title><link>http://m.tkk7.com/BaSaRa/archive/2006/06/02/49952.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Fri, 02 Jun 2006 07:59:00 GMT</pubDate><guid>http://m.tkk7.com/BaSaRa/archive/2006/06/02/49952.html</guid><wfw:comment>http://m.tkk7.com/BaSaRa/comments/49952.html</wfw:comment><comments>http://m.tkk7.com/BaSaRa/archive/2006/06/02/49952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/BaSaRa/comments/commentRss/49952.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/BaSaRa/services/trackbacks/49952.html</trackback:ping><description><![CDATA[<p>1.普通绑?br />dojo.event.connect(DOMNode, 'onclick', 'func');</p> <p>2.l定多个事g<br />dojo.event.connect(DOMNode, 'onclick', 'func1');<br />dojo.event.connect(DOMNode, 'onclick', 'func2');</p> <p>3.l定一个obj的两个方?br />dojo.event.connect(DOMNode, 'onclick', evtObj, 'func1');<br />dojo.event.connect(DOMNode, 'onclick', evtObj, 'func2');</p> <p>4.让绑定的事g序执行<br />var exampleObj = {<br />  counter: 0,<br />  foo: function(){ <br />    alert("foo");<br />    this.counter++;<br />  },<br />  bar: function(){<br />    alert("bar");<br />    this.counter++;<br />  }<br />};<br />dojo.event.connect(exampleObj, "foo", exampleObj, "bar"); // 调用foo的话bar也会执行<br />q样也可?br />dojo.event.kwConnect({<br /> type : 'before' // 让bar在foo之前执行<br /> srcObj : exampleObj,<br /> srcFunc : 'foo',<br /> targetObj : exampleObj,<br /> targetFunc : 'bar',<br /> delay : 2000 // bar延迟执行2U?br /> once : true // l定一?br />});<br />exampleObj.foo();</p> <p>5.先后执行<br />dojo.event.connect("after", exampleObj, "foo", exampleObj, "bar"); // bar在foo之后执行<br />dojo.event.connect("before", exampleObj, "foo", exampleObj, "bar"); // bar在foo之前执行</p> <p>6.传递参?br />var evtObj = function() {<br /> this.func1 = function(a) {<br />  return(function(e) {<br />   alert((e||window.event).type);<br />  })<br /> };<br /> this.func2 = function(b) {<br />  alert(b);      <br /> };<br />}</p> <p>var o = new evtObj();<br />var btn = dojo.byId("testBtn");<br />dojo.event.connect(btn, 'onclick', o.func1('hello'));</p> <p>以前一般这样写Q?br />function init() {<br />var evtObj = function() {<br /> this.func1 = function(a) {<br />  alert(a.type);<br /> };<br /> this.func2 = function(b) {<br />  alert(b);      <br /> };<br />}</p> <p>var o = new evtObj();<br />var btn = dojo.byId("testBtn");<br />dojo.event.connect(btn, 'onclick', function(event){o.func1(event)});<br />q样的话你在W三个参数就要传递eventQ很ȝ</p><img src ="http://m.tkk7.com/BaSaRa/aggbug/49952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-02 15:59 <a href="http://m.tkk7.com/BaSaRa/archive/2006/06/02/49952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单的定时器,不知道会不会存在内存泄露。。?/title><link>http://m.tkk7.com/BaSaRa/archive/2006/06/01/49565.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Thu, 01 Jun 2006 06:18:00 GMT</pubDate><guid>http://m.tkk7.com/BaSaRa/archive/2006/06/01/49565.html</guid><wfw:comment>http://m.tkk7.com/BaSaRa/comments/49565.html</wfw:comment><comments>http://m.tkk7.com/BaSaRa/archive/2006/06/01/49565.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/BaSaRa/comments/commentRss/49565.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/BaSaRa/services/trackbacks/49565.html</trackback:ping><description><![CDATA[<p><input type="button" id="btn" value="btn"/><br /><div id="div1" style="display:none;">I am tooltip</div></p> <p><script language="JavaScript"><br /><!--<br />// ҎA<br />var obj = {<br /> flag : null,<br /> setTime : function(n) {<br />  this.flag = setTimeout(function(){<br />   document.getElementById("div1").style.display = "";<br />  }, n);<br /> },<br /> clear  : function() {<br />  clearTimeout(this.flag);<br />  document.getElementById("div1").style.display = "none";<br /> }<br />}</p> <p>document.getElementById("btn").onmouseover = function() {obj.setTime(1000);};<br />document.getElementById("btn").onmouseout = function() {obj.clear();};<br />//--><br /></script></p> <p><script language="JavaScript"><br /><!--<br />//ҎB<br />//var flag;<br />//function setTime(time) {<br />// return(function(e){<br />//  flag=setTimeout(function() {<br />//   document.getElementById("div1").style.display = "";<br />//  }, time);<br />// });<br />//}<br />//function clear() {<br />// clearTimeout(flag);<br />// document.getElementById("div1").style.display = "none";<br />//}<br />//<br />//document.getElementById("btn").onmouseover = setTime(1000);<br />//document.getElementById("btn").onmouseout = clear;<br />//--><br /></script><br /><br />总觉得方法A和方法B都存在泄露隐患。。?/p><img src ="http://m.tkk7.com/BaSaRa/aggbug/49565.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-01 14:18 <a href="http://m.tkk7.com/BaSaRa/archive/2006/06/01/49565.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>怎样在不使用function(){ ... }情况下绑定事?/title><link>http://m.tkk7.com/BaSaRa/archive/2006/05/31/49310.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Wed, 31 May 2006 09:35:00 GMT</pubDate><guid>http://m.tkk7.com/BaSaRa/archive/2006/05/31/49310.html</guid><wfw:comment>http://m.tkk7.com/BaSaRa/comments/49310.html</wfw:comment><comments>http://m.tkk7.com/BaSaRa/archive/2006/05/31/49310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/BaSaRa/comments/commentRss/49310.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/BaSaRa/services/trackbacks/49310.html</trackback:ping><description><![CDATA[<p>一般写事gl定都是q样写的Q?br /><br />document.getElementById('btn').onclick = function() { func... }<br /><br />现在q样写:<br /><br /><input type="button" id="btn" value="hello"/></p> <p><script language="JavaScript"><br /><!--<br />function associate(str){<br />    return (function(e){  // event会默认传q去Q所以不用在associate的参数里传递event Q?associate(event) Q?br />        var _e = e||window.event;  // 在这里加入判断,兼容ff和ie<br />    doClick(_e, this, str);<br />    });<br />}</p> <p>function doClick(a, b, c) {<br /> alert(a.type);<br /> alert(b.type);<br /> alert(c);<br />}</p> <p>document.getElementById('btn').onclick = associate('hello');<br />//--><br /></script></p><img src ="http://m.tkk7.com/BaSaRa/aggbug/49310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/BaSaRa/" target="_blank">BaSaRa </a> 2006-05-31 17:35 <a href="http://m.tkk7.com/BaSaRa/archive/2006/05/31/49310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>msdn一关于内存泄漏的文章http://m.tkk7.com/BaSaRa/archive/2006/05/31/49213.htmlBaSaRa BaSaRa Wed, 31 May 2006 03:53:00 GMThttp://m.tkk7.com/BaSaRa/archive/2006/05/31/49213.htmlhttp://m.tkk7.com/BaSaRa/comments/49213.htmlhttp://m.tkk7.com/BaSaRa/archive/2006/05/31/49213.html#Feedback0http://m.tkk7.com/BaSaRa/comments/commentRss/49213.htmlhttp://m.tkk7.com/BaSaRa/services/trackbacks/49213.html    MSDN Home >  MSDN Library >  Web Development > 
 
Internet Explorer Development Technical Articles

Understanding and Solving Internet Explorer Leak Patterns

Justin Rogers
Microsoft Corporation

June 2005

The Evolution of the Web Developer

In the past, memory leaks haven't posed huge problems for Web developers. Pages were kept relatively simple and navigation between different locations within a site was a great way to clean up any loose memory. If there was a leak, it was most likely small enough to go unnoticed.

New Web applications live up to higher standards. A page might run for hours without being navigated and retrieve updated information dynamically through Web services. Language features are pushed to the breaking point by combining complex event schemes, object-oriented JScript, and closures to produce entire applications. With these and other changes, certain memory leak patterns are becoming more prominent, especially those previously hidden by navigation.

The good news is that memory leak patterns can be easily spotted if you know what to look for. Most of the troublesome patterns you might face have known workarounds requiring only a small amount of extra work on your behalf. While some pages might still fall prey to small memory leaks, the most noticeable ones can be easily removed.

Leak Patterns

The following sections will discuss patterns of memory leaks and point out some common examples of each pattern. One great example of a pattern is the closure feature of JScript, while another example is the use of closures in hooking events. If you're familiar with the event hooking example, you might be able to find and fix many of your memory leaks, but other closure-related issues might go unnoticed.

Now, let's look at the following patterns:

  1. Circular References—When mutual references are counted between Internet Explorer's COM infrastructure and any scripting engine, objects can leak memory. This is the broadest pattern.

  2. Closures—Closures are a specific form of circular reference that pose the largest pattern to existing Web application architectures. Closures are easy to spot because they rely on a specific language keyword and can be searched for generically.

  3. Cross-Page Leaks—Cross-page leaks are often very small leaks of internal book-keeping objects as you move from site to site. We'll examine the DOM Insertion Order issue, along with a workaround that shows how small changes to your code can prevent the creation of these book-keeping objects.

  4. Pseudo-Leaks—These aren't really leaks, but can be extremely annoying if you don't understand where your memory is going. We'll examine the script element rewriting and how it appears to leak quite a bit of memory, when it is really performing as required.

Circular References

Circular references are the root of nearly every leak. Normally, script engines handle circular references through their garbage collectors, but certain unknowns can prevent their heuristics from working properly. The unknown in the case of IE would be the status of any DOM elements that a portion of script has access to. The basic principle would be as follows:

Figure 1 Basic Circular Reference Pattern

Figure 1. Basic Circular Reference Pattern

The cause of the leak in this pattern is based on COM reference counting. The script engine objects will hold a reference to the DOM element and will be waiting for any outstanding references to be removed before cleaning up and releasing the DOM element pointer. In our case we have two references on the script engine object: the script engine scope, and the DOM element expando property. While terminating the script engine will release the first reference, the DOM element reference will never be released because it is waiting on the script engine object to release it! You might think it would be easy to detect this scenario and fix the problem, but in practice the basic case presented is only the tip of the iceberg. You could have circular references at the end of a 30 object chain and those would be much harder to detect.

If you are wondering what this pattern looks like in HTML, you can cause a leak by using a global script engine variable and a DOM element as shown.

												<html>
    <head>
        <script language="JScript">

        var myGlobalObject;

        function SetupLeak()
        {
            // First set up the script scope to element reference
            myGlobalObject =
                document.getElementById("LeakedDiv");

            // Next set up the element to script scope reference
            document.getElementById("LeakedDiv").expandoProperty =
                myGlobalObject;
        }


        function BreakLeak()
        {
            document.getElementById("LeakedDiv").expandoProperty =
                null;
        }
        </script>
    </head>

    <body onload="SetupLeak()" onunload="BreakLeak()">
        <div id="LeakedDiv"></div>
    </body>
</html>
										

To break the leak pattern you can make use of explicit null assignments. By assigning null before the document unloads you are telling the script engine there is no longer an association between the element and the object inside the engine. It can now properly clean up references and will release the DOM element. In this case, you as the Web developer know more about the relationships between your objects than the script engine does.

While that is the basic pattern, it can be difficult to spot more complex scenarios. A common usage of object-oriented JScript is to extend DOM elements by encapsulating them inside of a JScript object. During the construction process, you generally pass in the DOM element you want to attach to and then store a reference to the DOM element on the newly constructed object while at the same time storing an instance of the newly constructed object on the DOM element. That way your application model always has access to everything it needs. The problem is this is a very explicit circular reference, but because it uses different language aspects it might go unnoticed. Breaking up this kind of pattern can become more complex, and you can use the same simple methods discussed earlier.

												<html>
    <head>
        <script language="JScript">

        function Encapsulator(element)
        {
            // Set up our element
            this.elementReference = element;

            // Make our circular reference
            element.expandoProperty = this;
        }

        function SetupLeak()
        {
            // The leak happens all at once
            new Encapsulator(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").expandoProperty =
                null;
        }
        </script>
    </head>

    <body onload="SetupLeak()" onunload="BreakLeak()">
        <div id="LeakedDiv"></div>
    </body>
</html>

										

More complex solutions to this problem involve registration schemes to note which elements/properties need to be unhooked, having the peer element hook events so that it can clean up before the document unloads, but often you can run into additional leak patterns without actually fixing the problem.

Closures

Closures are very often responsible for leaks because they create circular references without the programmer being fully aware. It isn't immediately obvious that parent function parameters and local variables will be frozen in time, referenced, and held until the closure itself is released. In fact this has become such a common programming tactic, and users have run into issues so often, there are quite a few resources already available. Because they detail some of the history behind closures as well as some of the specific instances of closure leaks we'll check those out after applying the closure model to our circular reference diagram and figuring out where these extra references are coming from.

Figure 2 Circular References with Closures

Figure 2. Circular References with Closures

With normal circular references there were two solid objects holding references to each other, but closures are different. Rather than make the references directly, they are made instead by importing information from their parent function's scope. Normally, a function's local variables and the parameters used when calling a function only exist for the lifetime of the function itself. With closures, these variables and parameters continue to have an outstanding reference as long as the closure is alive, and since closures can live beyond the lifetime of their parent function so can any of the locals and parameters in that function. In the example, Parameter 1 would normally be released as soon as the function call was over. Because we've added a closure, a second reference is made, and that second reference won't be released until the closure is also released. If you happened to attach the closure to an event, then you would have to detach it from that event. If you happened to attach the closure to an expando then you would need to null that expando.

Closures are also created per call, so calling this function twice will create two individual closures, each holding references to the parameters passed in each time. Because of this transparent nature it is really easy to leak closures. The following example provides the most basic of leaks using closures:

												<html>
    <head>
        <script language="JScript">

        function AttachEvents(element)
        {
            // This structure causes element to ref ClickEventHandler
            element.attachEvent("onclick", ClickEventHandler);

            function ClickEventHandler()
            {
                // This closure refs element
            }
        }

        function SetupLeak()
        {
            // The leak happens all at once
            AttachEvents(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
        }
        </script>
    </head\>

    <body onload="SetupLeak()" onunload="BreakLeak()">
        <div id="LeakedDiv"></div>
    </body>
</html>
										

If you are wondering how to break this leak, it won't be as easy as a normal circular reference. The "closure" can be viewed as a temporary object that exists in the function scope. Once the function exits, you lose reference to the closure itself, so what would you end up calling detachEvent with? One of the most interesting approaches to this problem was demonstrated on MSN spaces thanks to Scott Isaacs. The approach uses a second closure to additionally hook the window's onUnload event, and because this closure has the same "scoped" objects it is able to detach the event, detach itself, and finish the clean up process. To make everything easily fit with our model we can also store the closure on an expando, detach it, and then null the expando, as in the following example.

												<html>
    <head>
        <script language="JScript">

        function AttachEvents(element)
        {
            // In order to remove this we need to put
            // it somewhere. Creates another ref
            element.expandoClick = ClickEventHandler;

            // This structure causes element to ref ClickEventHandler
            element.attachEvent("onclick", element.expandoClick);

            function ClickEventHandler()
            {
                // This closure refs element
            }
        }

        function SetupLeak()
        {
            // The leak happens all at once
            AttachEvents(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").detachEvent("onclick",
                document.getElementById("LeakedDiv").expandoClick);
            document.getElementById("LeakedDiv").expandoClick = null;
        }
        </script>
    </head>

    <body onload="SetupLeak()" onunload="BreakLeak()">
        <div id="LeakedDiv"></div>
    </body>
</html>
										

In a Knowledge Base article, we actually recommend that you try not to use closures unless they are necessary. In the example, I've given we don't need to use a closure as the event handler, instead we can move the closure to a global scope. When the closure becomes a function, it no longer inherits the parameters or local variables from its parent function so we don't have to worry about closure-based circular references at all. Most code can be fixed by creating an architecture that doesn't rely on closures where they aren't necessary.

Finally, Eric Lippert, one of the developers of the scripting engines, has a great post on closures in general. His final recommendations are also along the lines of only using closures when truly necessary. While his article doesn't mention any of the workarounds for the closure pattern, hopefully we've covered enough examples here to get you started.

Cross-Page Leaks

Leaks that are based on order of insertion are almost always caused by the creation of intermediate objects that don't get cleaned up properly. That is exactly the case when creating dynamic elements and then attaching them to the DOM. The basic pattern is attaching two dynamically created objects together temporarily which creates a scope from the child to the parent element. Later, when you attach this two-element tree to the primary tree, they both inherit the scope of the document and a temporary object is leaked. The following diagram shows two methods for attaching dynamically created elements to the tree. In the first model, attach each child element to its parent, and finally attach the entire subtree to the primary tree. This method can cause leaks through temporary objects if other conditions are met. In the second model, we attach elements into the primary tree working our way from top-level dynamically created element down through all of the children. Because each attachment inherits the scope of the primary document we never generate temporary scopes. This method is much better at avoiding potential memory leaks.

Figure 3 DOM Insertion Order Leak Model

Figure 3. DOM Insertion Order Leak Model

Next, we are going to cover an example of a leak that is transparent to most leak-detection algorithms. Because we don't leak any publicly visible elements and the objects we leak are very small you might never notice this problem. For our example to work, the dynamically created elements will have to contain a script pointer in the form of an inline function. This will allow us to leak an internal script object that is created temporarily as we attach elements together. Because the leak is small, we'll have to run thousands of samples. In fact, the objects leaked are only a few bytes. By running the sample and navigating to an empty page, you can see the difference in memory consumption between the two versions. When we use the first DOM model of attaching child to parent, then parent to the primary tree, our memory usage goes up a bit. This is a cross-navigation leak and the memory isn't reclaimed until you restart the IE process. If you run the sample a few more times, using the second DOM model of attaching the parent to the primary tree and then the child to the parent, your memory won't continue to climb and you'll find that you've fixed the cross-page navigation leak.

												<html>
    <head>
        <script language="JScript">

        function LeakMemory()
        {
            var hostElement = document.getElementById("hostElement");

            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i < 5000; i++)
            {
                var parentDiv =
                    document.createElement("<div onClick='foo()'>");
                var childDiv =
                    document.createElement("<div onClick='foo()'>");

                // This will leak a temporary object
                parentDiv.appendChild(childDiv);
                hostElement.appendChild(parentDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv = null;
                childDiv = null;
            }
            hostElement = null;
        }


        function CleanMemory()
        {
            var hostElement = document.getElementById("hostElement");

            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i < 5000; i++)
            {
                var parentDiv =
                    document.createElement("<div onClick='foo()'>");
                var childDiv =
                    document.createElement("<div onClick='foo()'>");

                // Changing the order is important, this won't leak
                hostElement.appendChild(parentDiv);
                parentDiv.appendChild(childDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv = null;
                childDiv = null;
            }
            hostElement = null;
        }
        </script>
    </head>

    <body>
        <button onclick="LeakMemory()">Memory Leaking Insert</button>
        <button onclick="CleanMemory()">Clean Insert</button>
        <div id="hostElement"></div>
    </body>
</html>
										

This leak deserves clarification, because our workaround goes against some best practices in IE. The key points to understand about the leak are that DOM elements are being created with scripts already attached. This is actually crucial to the leak, because if we create DOM elements that don't contain any script and attach them together in the same manner we don't have a leak problem. This gives rise to a second workaround that might be even better for larger subtrees (in the example we only have two elements, so building the tree off the primary DOM isn't a performance hit). The second workaround would be to create your elements with no scripts attached initially so that you can safely build your subtree. After you've attached your subtree to the primary DOM, go back and wire up any script events at that point. Remember to follow the principles for circular references and closures so you don't cause a different leak in your code as you hook up your events.

I really wanted to point out this issue because it shows that not all memory leaks are easy to find. It could take thousands of iterations of a smaller pattern to become visible, and it might be something slight, like the order of insertion of DOM elements that causes the problem to arise. If you tend to program using only best practices, then you think you are safe, but this leak shows that even best practices can exhibit leaks. Our solution here was to improve upon the best practice or even introduce a new best practice in order to remove the leaking condition.

Pseudo-Leaks

Often times the actual behavior and expected behavior of some APIs can lead you to misdiagnose memory leaks. Pseudo-leaks almost always appear on the same page during dynamic scripting operations and should rarely be visible after navigation away from the page to a blank page. That is how you can eliminate the issue as a cross-page leak and then start to work on whether the memory consumption is expected. We'll use script text rewriting as our example of a pseudo-leak.

Like the DOM Insertion Order issue, this issue also relies on the creation of temporary objects in order to "leak" memory. By rewriting the script text inside of a script element over and over again, slowly you'll begin to leak various script engine objects that were attached to the previous contents. In particular, objects related to debugging script are left behind as are fully formed code elements.

												<html>
    <head>
        <script language="JScript">

        function LeakMemory()
        {
            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i < 5000; i++)
            {
                hostElement.text = "function foo() { }";
            }
        }
        </script>
    </head>

    <body>
        <button onclick="LeakMemory()">Memory Leaking Insert</button>
        <script id="hostElement">function foo() { }</script>
    </body>
</html>
										

If you run the above code and use the Task Manager trick again, while navigating between the "leaking" page and a blank page, you won't notice a script leak. This script leak is entirely within a page and when you navigate away then you get your memory back. The reason this one is bad is due to expected behavior. You expect that after rewriting some script that the original script won't stay around. But it really has to, because it might have been used already for event attachments and there might be outstanding reference counts. As you can see, this is a pseudo-leak. On the surface the amount of memory consumption looks really bad, but there is a completely valid reason.

Conclusion

Every Web developer builds a personal list of code examples that they know leak and learns to work around those leaks when they see them in code. This is extremely handy and is the reason the Web is relatively leak-free today. Thinking about the leaks in terms of patterns instead of individual code examples, you can start to develop even better strategies for dealing with them. The idea is to take them into account during the design phase and make sure you have plans for any potential leaks. Use defensive coding practices and assume that you'll need to clean up all your own memory. While this is an overstatement of the problem, you very rarely need to clean up your own memory; it becomes obvious which variables and expando properties have the potential for leaking.

In the interest of patterns and design I highly recommend because it demonstrates a general purpose example of removing all closure-based leaks. It does require a bit more code, but the practice is sound and the improved pattern is easy to spot in code and to debug. Similar registration schemes can be used for expando-based circular references as long as care is taken that the registration method itself isn't riddled with leaks (especially where closures are used)!


About the author

Justin Rogers recently joined the Internet Explorer team as an Object Model developer working on extensibility and previously worked on such notable projects as the .NET QuickStart Tutorials, .NET Terrarium, and SQL Reporting Services Management Studio in SQL Server 2005.



  


© 2006 Microsoft Corporation. All rights reserved.  Terms of Use | Trademarks | Privacy Statement
Microsoft


BaSaRa 2006-05-31 11:53 发表评论
]]>
java里面的P代器模式(Iterator)解释http://m.tkk7.com/BaSaRa/archive/2006/05/31/49173.htmlBaSaRa BaSaRa Wed, 31 May 2006 01:56:00 GMThttp://m.tkk7.com/BaSaRa/archive/2006/05/31/49173.htmlhttp://m.tkk7.com/BaSaRa/comments/49173.htmlhttp://m.tkk7.com/BaSaRa/archive/2006/05/31/49173.html#Feedback1http://m.tkk7.com/BaSaRa/comments/commentRss/49173.htmlhttp://m.tkk7.com/BaSaRa/services/trackbacks/49173.html
用Iterator模式实现遍历集合
 
  Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合cM抽象出来Q从而避免向客户端暴露集合的内部l构?br />
  例如Q如果没有用IteratorQ遍历一个数l的Ҏ是用烦引:
         for(int i=0; i<array.size(); i++) { ... get(i) ... }

  而访问一个链表(LinkedListQ又必须使用while循环Q?br />         while((e=e.next())!=null) { ... e.data() ... }

  以上两种Ҏ客户端都必须事先知道集合的内部结构,讉K代码和集合本w是紧耦合Q无法将讉K逻辑从集合类和客L代码中分d来,每一U集合对应一U遍历方法,客户端代码无法复用?br />
  更恐怖的是,如果以后需要把ArrayList更换为LinkedListQ则原来的客L代码必须全部重写?br />
  决以上问题,Iterator模式L用同一U逻辑来遍历集合:
         for(Iterator it = c.iterater(); it.hasNext(); ) { ... }

  奥秘在于客户端自w不l护遍历集合?quot;指针"Q所有的内部状态(如当前元素位|,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂Ҏ生成Q因此,它知道如何遍历整个集合?br />
  客户端从不直接和集合cL交道Q它L控制IteratorQ向它发?quot;向前"Q?quot;向后"Q?quot;取当前元?quot;的命令,可以间接遍历整个集合?br />

q样看来实现Iterator的目的是降低耦合以及实现l一的遍历模式吧?br />在JS里面Q遍历数l和遍历Object是不一LQ一般数l是 for(i=0; i<length; i++) q样QObjectp for in 了,用了Iterator后可以达到写法的一_׃用管需要遍历的是什么类型对象了?img src ="http://m.tkk7.com/BaSaRa/aggbug/49173.html" width = "1" height = "1" />

BaSaRa 2006-05-31 09:56 发表评论
]]>
关于javascript中的this...http://m.tkk7.com/BaSaRa/archive/2006/05/30/49049.htmlBaSaRa BaSaRa Tue, 30 May 2006 08:37:00 GMThttp://m.tkk7.com/BaSaRa/archive/2006/05/30/49049.htmlhttp://m.tkk7.com/BaSaRa/comments/49049.htmlhttp://m.tkk7.com/BaSaRa/archive/2006/05/30/49049.html#Feedback0http://m.tkk7.com/BaSaRa/comments/commentRss/49049.htmlhttp://m.tkk7.com/BaSaRa/services/trackbacks/49049.html
var myObj=new Object();
myObj.message="hello world";
myObj.fun=function(){
alert (this.message);

}

window.onload=myObj.fun;

面打开时显CZ么?hello world?

不对Q是undefinedQ!
 
晕不晕?反正当我真正开始在js中运用OO概念q行~程的时候发玎ͼthis所指代的对象竟然和直觉不一致。后来查资料知道Q在html事g响应函数中的this都会被替换成触发事g的那个ElementQ!Q这U说法不太严谨,不过意思可以理解,Q嘻嘻)所以window.onload的时候调用的fun已经不是myObj的fun了。?br />
 改一下代码:
<script language="JavaScript">
<!--
var myObj= {};
myObj.message="hello world";
myObj.fun=function(){
 alert (this.fun);
}
window.fun = "test";
window.onload=myObj.fun;
//-->
</script>

。。。有Ҏ?br />

BaSaRa 2006-05-30 16:37 发表评论
]]>
վ֩ģ壺 վ߹ۿ| ޾Ʒþþþþþ| Ļ޾Ʒ| ѿAAƬƵ| ˳˳ۺ| þҹҹ³³ƬӰ| ۺ޹| þþƷ7777| AƬ߹ۿ| AVպAV| 91Ʒֻ| Ʒ˿Ļ| ֻùۿ| ƷѹۿƵ| | þþƷӰѶ| youjizz| ĻӰѹۿ| պŷһѹۿ| þþƷձҰ| ˵һaվ| þùɫAVѿ| ˬִ̼վ| ޾ƷպAV | þþþþƵ| 97Ƶ| ߿Ƭ˳Ӿ| ҹѸСӰ| ŮƷĻ| ҹ| AVѿ| ƷһëƬ| ƵƬ߹ۿ| ţţ߾ƷƵۿ| ҹδʮ| ԭƷav| ޾Ʒ| av| þ޹ӰԺ| Ʒ޾ƷþþƷ| ɫݺɫۺƵ|