ChinaStock全程解析

| |
[不指定 2009/02/23 05:32 | by ping ]
插件
http://www.zeali.net/ffexts/chinastock/chinastock.xpi

调试以下部分,采用venkman
chrome://chinastock/content/detail.xul


入口函数:
=》chinastock_detail_init();

=》gZealChinaStock.m_prefs = XPComponent;

=》gZealChinaStock.initLogHandler();

=》stockstrs = gZealChinaStock.get_stockstrs();
//"000960,600291,600367,600196"

=》gZealChinaStock.parse_stockinfo(stockstrs);

=》zealParseRURL();

=》ElE('tradeDetailLink').href = 'javascript:chinastock_goto_with(\'http://bill.finance.sina.com.cn/bill/trade_item.php?stock_code=%stockfixid%\')';

=》ElE('tradeBigLink').href = 'javascript:chinastock_goto_with(\'http://bill.finance.sina.com.cn/bill/detail.php?bill_size=40000&stock_code=%stockfixid%\')';  

=》sNamecache = "";

=》sNamecache = sNamecache.split("##");
//"!\x1A\xA1\xFD##\x7F4\xA1\xFD##\xA2\x1F\xD1U##\r\x1F;o"

=》switcherBox = ElE('stocklistswitcher');

=》for(var i=0;i<gZealChinaStock.m_stock_list.length;i++){
//4

=》if(i >= sNamecache.length){

=》sNamecache[sNamecache.length] = "";

=》 if(sNamecache.length < 1) sNamecache = gZealChinaStock.m_stock_list.m_sFixid;

=》switcherBox.appendItem(gZealChinaStock.m_stock_list.m_sId+" ("+sNamecache+")",i);

=》}//end of for  loop

=》sNamecache = null;

=》switcherBox.selectedIndex = detailPosToDealNow;

=》switcherBox = null;

=》chinastock_detail_switchpos();
//0

在DTD中,还可以声明一些称为Entity的东西,让DTD和XML文件使用。我们可以把Entity看作是一个常量,它有一定的值。在DTD中,Entity的声明语法为:〈!ENTITY entity-name entity-definition〉。例如:我们在DTD中声明〈!ENTITY PC "(#PCDATA)"〉 ,那么在后面的元素设定中,就可以使用这个Entity来代替“(#PCDATA)”这个字符串,如:〈!ELEMENT 作者 (#PCDATA)〉可以写成〈!ELEMENT 作者 &&PC;〉。引用Entity的时候,必须要在Entity名称前面加上“&&”符号,后面加上“;”符号。

[img][attach]96[/attach][/img]

2009年新年第一贴,好运接力贴 T楼送车厢
让Firefox插件有属性
为程序添加属性单。

1。要启用Firefox或者说Mozilla的[属性,高级,或者说preferences ],必须提到如下三个:

nsIPrefService, nsIPrefBranch and nsIPrefBranch2.

注:nsIPref 被放弃了。

2。启用:
var pref =
Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService)
.getBranch("");
从而获得nsIPrefBranch 对象实例。

3。nsIPrefBranch 有如下 成对的函数:
针对:string  integer boolean
getBoolPref(), setBoolPref();
getCharPref(), setCharPref();
getIntPref(),setIntPref();
setComplexValue(),getComplexValue();

4。存取:

var value = prefs.getBoolPref("accessibility.typeaheadfind"); // get a pref
prefs.setBoolPref("accessibility.typeaheadfind", !value); // set a pref

void getComplexValue(in string aPrefName, in nsIIDRef aType,
                     [iid_is(aType), retval] out nsQIResult aValue);
void setComplexValue(in string aPrefName, in nsIIDRef aType, in nsISupports aValue);
aType : nsISupportsString:处理宽字符的字符窜。

// prefs is an nsIPrefBranch

// Example 1: getting Unicode value
var value = prefs.getComplexValue("preference.with.non.ascii.value",
      Components.interfaces.nsISupportsString).data;

// Example 2: setting Unicode value
var str = Components.classes["@mozilla.org/supports-string;1"]
      .createInstance(Components.interfaces.nsISupportsString);
str.data = "some non-ascii text";
prefs.setComplexValue("preference.with.non.ascii.value",
      Components.interfaces.nsISupportsString, str);
nsIPrefLocalizedString:处理宽字符的字符窜,但是也有特别情况,比如本地化。
extensions.myext.welcomemessage=Localized default value
pref("extensions.myext.welcomemessage", "chrome://myext/locale/defaults.properties");
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
      getService(Components.interfaces.nsIPrefService);
var branch = prefs.getBranch("extensions.myext.");
var value = branch.getComplexValue("welcomemessage",
      Components.interfaces.nsIPrefLocalizedString).data;
Mozilla的解释:
The code in step 3 will read the default value from
chrome://myext/locale/defaults.properties when no user value is set,
and will behave exactly the same as if nsISupportsString was passed as aType otherwise.nsILocalFile :处理一般绝对目录。
nsIRelativeFilePref:处理操作系统特殊目录,业内人士应该都知道。

关于onreadystatechange应用
JavaScript来创建XMLHttpRequest类向服务器发送一个HTTP请求后,接下来要决定当收到服务器的响应后,需要做什么。
这需要告诉HTTP请求对象用哪一个JavaScript函数处理这个响应。
可以将对象的onreadystatechange属性设置为要使用的JavaScript的函数名,如下所示:

xmlhttp_request.onreadystatechange =FunctionName;

FunctionName是用JavaScript创建的函数名,注意不要写成FunctionName(),当然我们也可以直接将JavaScript代码创建在onreadystatechange之后,例如:
xmlhttp_request.onreadystatechange = function(){
  // JavaScript代码段
};

在这个函数中。首先要检查请求的状态。只有当一个完整的服务器响应已经收到了,函数才可以处理该响应。XMLHttpRequest 提供了readyState属性来对服务器响应进行判断。
readyState的取值如下:
0 (未初始化)
1 (正在装载)
2 (装载完毕)
3 (交互中)
4 (完成)
所以只有当readyState=4时,一个完整的服务器响应已经收到了,函数才可以处理该响应。具体代码如下:
if (http_request.readyState == 4)
{
  // 收到完整的服务器响应
}
else
{
  // 没有收到完整的服务器响应
}

当readyState=4时,一个完整的服务器响应已经收到了,接着,函数会检查HTTP服务器响应的状态值。完整的状态取值可参见W3C文档。当HTTP服务器响应的值为200时,表示状态正常。
在检查完请求的状态值和响应的HTTP状态值后,就可以处理从服务器得到的数据了。有两种方式可以得到这些数据:
(1)以文本字符串的方式返回服务器的响应
(2)以XMLDocument对象方式返回响应
gZealChinaStock.m_ajaxRequest.open( "GET", 'http://finance.sina.com.cn/realstock/company/'+curStock.m_sFixid+'/nc.shtml' );

http://finance.sina.com.cn/realstock/company/sz000960/nc.shtml

var picpat = new RegExp('<td width="50%" align="center"><img src="(*\\.sinaimg\\.cn/cj/realstock/company/]http://i[0-9]*\\.sinaimg\\.cn/cj/realstock/company/'+curStock.m_sFixid+'/[^\\.]+\\.jpg)" border="0" /></td>','g');

<td width="50%" align="center"><img src="http://i1.sinaimg.cn/cj/realstock/company/sz000960/1228840455_uBmBKl.jpg" border="0" />

<td width="50%" align="center"><img src="http://i0.sinaimg.cn/cj/realstock/company/sz000960/1228840455_JOdfdq.jpg" border="0" />
火车头专家采集队伍,为您提供一流的采集服务-技术有保障,安全有保障
下面的这些配置可以使开发调试扩展更加方便。
查看 Editing Configuration Files 了解更多信息。
下面的这些选项,默认是不会在about:config中列出来的,所以需要手工添加它们。


browser.dom.window.dump.enabled = true. 允许使用dump() 命令输出信息到标准控制台

-  792     log: function(nLevel, sMsg) {
-  793         if (!this.m_debug) return;
    794        
-  795         var rDate = new Date();
-  796         if (this.m_csk_logger) {
-  797             this.m_csk_logger.log(nLevel, rDate.getTime()+': '+sMsg);
    798         } else {
-  799             window.dump(rDate.getTime()+': '+sMsg+"\n");
    800         }
var globalStockBase = {
lta: 0.0,
lastfive: 0.0,
flag: 0, //判断标志
totalcapital: 0.0, //总股本
currcapital: 0.0, //流通股本
curracapital: 0, //流通A股
currbcapital: 0, //流通B股
currbLast: 0.00, //流通B股当前价
curraLast: 0.00, //流通A股当前价
exchangerate: 0.00 //汇率
};

var fullcode="sz000960";
var stockname="锡业股份";
var chart_img_alt = "锡业股份 000960 行情图";
var lta = 25711.0581;
var lastfive = 85.167503;
var flag = 1; //判断标志
var totalcapital = 65072.032; //总股本
var currcapital = 31502.5817; //流通股本
var curracapital = 0; //流通A股
var currbcapital = 0; //流通B股
var currbLast = 0.00; //流通B股当前价
var curraLast = 0.00; //流通A股当前价
var exchangerate = 0.00; //汇率
var detailcache = new Array();
var relative_stocks_sz000960= {sh600459 : '',sh600432 : '',sh600456 : '',sz000612 : '',sz000751 : '',sz000831 : ''};
var corr_future = ['cu0901'];

---code here---
-  158               for(var basekey in globalStockBase){
-  159                       var stockpattern = new RegExp('var '+basekey+' = ([^;]+);','g');
-  160                       var matches = stockpattern.exec(gZealChinaStock.m_ajaxRequest.responseText);
-  161                       if(null != matches && matches.length >= 2){
-  162                           globalStockBase[basekey] = matches[1];
-  163                           gZealChinaStock.log(5, 'getshtml bingo for '+stockpattern+' = '+globalStockBase[basekey]);
    164                       }
    165                       else{
-  166                           bmatched = false;
    167                       }
TEST YOURSELF 采集水平自我测试
setTimeout和setInterval的使用
这两个方法都可以用来实现在一个固定时间段之后去执行JavaScript。不过两者各有各的应用场景。
方 法实际上,setTimeout和setInterval的语法相同。它们都有两个参数,一个是将要执行的代码字符串,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将执行那段代码。
不过这两个函数还是有区别的,setInterval在执行完一次代码之后,经过了那个固定的时间间隔,它还会自动重复执行代码,而setTimeout只执行一次那段代码。
虽然表面上看来setTimeout只能应用在on-off方式的动作上,不过可以通过创建一个函数循环重复调用setTimeout,以实现重复的操作:
File: settimeout_setinterval.js

showTime();
function showTime()
{
    var today = new Date();
    alert("The time is: " + today.toString());
    setTimeout("showTime()", 5000);
}
一旦调用了这个函数,那么就会每隔5秒钟就显示一次时间。如果使用setInterval,则相应的代码如下所示:
File: settimeout_setinterval2.js

setInterval("showTime()", 5000);
function showTime()
{
    var today = new Date();
    alert("The time is: " + today.toString());
}
这两种方法可能看起来非常像,而且显示的结果也会很相似,不过两者的最大区别就是,setTimeout方法不会每隔5秒钟就执行一次showTime函数,它是在每次调用setTimeout后过5秒钟再去执行showTime函数。这意味着如果showTime函数的主体部分需要2秒钟执行完,那么整个函数则要每7秒钟才执行一次。而setInterval却没有被自己所调用的函数所束缚,它只是简单地每隔一定时间就重复执行一次那个函数。
如果要求在每隔一个固定的时间间隔后就精确地执行某动作,那么最好使用setInterval,而如果不想由于连续调用产生互相干扰的问题,尤其是每次函数的调用需要繁重的计算以及很长的处理时间,那么最好使用setTimeout。

---code here---
if(bmatched) setTimeout(chinastock_detail_getinfo,20);
-  108   function chinastock_detail_sTrendImg(type){
-  109     var curStock = gZealChinaStock.m_stock_list[detailPosToDealNow];
-  110     type = type || 'min';
-  111     ElE('csk-detail-trendimg').src = 'http://image.sinajs.cn/newchart/'+type+'/n/'+curStock.m_sFixid+'.gif?'+(new Date()).getTime();
    112 }

http://image.sinajs.cn/newchart/min/n/sz000960.gif?1228922353165

-  245     gZealChinaStock.m_ajaxRequest.open( "GET", 'http://hq.sinajs.cn/format=js&list='+curStock.m_sFixid+','+bigStocks.join(',') );
B  246     gZealChinaStock.m_ajaxRequest.setRequestHeader( "User-Agent", "Mozilla/4.0 (compatible; FirefoxExtensions CSK1.0; Windows XP 5.1)" );
-  247     gZealChinaStock.m_ajaxRequest.setRequestHeader("X-Requested-With", "XMLHttpRequest");
-  248     gZealChinaStock.m_ajaxRequest.send( null );

var stockpattern = new RegExp('var hq_str_'+curStock.m_sFixid+'="([^"]+)";','g')

http://hq.sinajs.cn/format=js&list=sz000960,s_sh000001,s_sz399001,s_sz399106,s_sh000300

var hq_str_sz000960="锡业股份,13.45,13.62,13.64,13.73,13.00,13.64,13.65,14125844,189541907.87,16018,13.64,32850,13.63,14800,13.62,46010,13.61,77700,13.60,54472,13.65,32700,13.66,17525,13.67,36200,13.68,58000,13.69,2008-12-10,15:05:58";
var hq_str_s_sh000001="上证指数,2079.117,41.377,2.03,1282510,9307744";
var hq_str_s_sz399001="深证成指,7490.289,129.300,1.76,9785444,988818";
var hq_str_s_sz399106="深证综指,624.331,14.141,2.32,17803610,4096815";
var hq_str_s_sh000300="沪深300,2096.393,55.546,2.72,832710,7075138";

var infolist = gZealChinaStock.m_ajaxRequest.responseText.split("\n").join("").split("\r").join("").split(';');
infolist =
"var hq_str_sh600036=\"\u62DB\u5546\u94F6\u884C,14.17,14.40,14.09,14.20,13.78,14.06,14.09,54791076,768929403,23900,14.06,45500,14.05,16700,14.04,51600,14.03,2900,14.02,37200,14.09,17197,14.10,50200,14.11,18300,14.12,53943,14.13,2008-12-11,10:41:38\";var hq_str_s_sh000001=\"\u4E0A\u8BC1\u6307\u6570,2070.440,-8.677,-0.42,466383,3465264\";var hq_str_s_sz399001=\"\u6DF1\u8BC1\u6210\u6307,7517.133,26.844,0.36,3508844,371780\";var hq_str_s_sz399106=\"\u6DF1\u8BC1\u7EFC\u6307,624.146,-0.185,-0.03,4274145782,1521579\";var hq_str_s_sh000300=\"\u6CAA\u6DF1300,2088.735,-7.658,-0.37,286379,2540317\";"

chinastock.xul
chrome://chinastock/content/chinastock.xul
<stringbundleset id="chinastock-stringbundleset">
        <stringbundle id="chinastock-bundle" src="chrome://chinastock/locale/chinastock.properties"/>
    </stringbundleset>

   XUL 提供的 stringbundle 元素
在 content 文件夹中,用文本编辑器打开 overlay.js 文件。你可以看到下面这样一段代码,它在变量中定义了一个确认对话框。
var bConfirmed = window.confirm("Welcome to Hello World! Click OK to continue.");
我们希望可以把对话框中的文本“Welcome to Hello World! Click OK to continue.”放到语言包中去,那样就可以把它翻译成其他语言,从而实现脚本文件的本地化。

在 en-US 文件夹中新建文本文件,重命名为“overlay.properties”。
       chrome/
       └ helloworld/
         ├ skin/
         ├ content/
         └ locale/
           └ en-US/
             ├ helloworld.dtd
             ├ overlay.dtd
             └ overlay.properties
打开 overlay.properties 文件,在其中添加如下一行代码,定义一组 String Bundles,为前面提到的确认对话框中的文本定义一个简短的标识名称(Identifier)。
SayHello_Confirm=Welcome to Hello World! Click OK to continue.
注意 properies 文件中 String Bundles 的语法格式是:
名称=文本
将来 javascript 脚本文件可以根据标识名称到 properties 文件中引用需要显示的文本。请注意用 Escaped Unicode 编码格式保存编辑完成的 properties 文件。

我们已经准备好了 properties 文件,现在还需要让 javascript 脚本文件能够引用 properties 文件中的文本。
XUL 提供的 stringbundle 元素(Element)可以帮助我们完成这项工作。stringbundle元素包括许多特性(Properties)和方法(Methods),利用它们就可以返回 properties 文件中的文本。下面用到的getString 是其中一个比较简单的方法。
首先需要确定是哪一个 XUL 文件调用了这个 javascript 脚本文件。查看 content 文件夹中的几个 XUL文件,你可以在 overlay.xul 文件的前面几行中找到如下一行代码,依据它我们可以判断正是 overlay.xul 调用的overlay.js 脚本文件。
<script type="application/x-javascript" src="overlay.js"/>
在 overlay.xul 文件中紧接上面这行代码添加这样一段代码:
<stringbundleset id="stringbundleset">
  <stringbundle id="helloworld-strings" src="chrome://helloworld/locale/overlay.properties" />
</stringbundleset>
这段代码定义了一个 stringbundle 元素,并指出保存 String Bundles 的 overlay.properties 文件的位置。
注意,通常情况下,一个 XUL 文件可能会调用多个 javascript 脚本文件。那么在这个 XUL文件里,必须为它调用的每一个脚本文件定义对应的 stringbundle 元素,使脚本文件可以找到它需要的 properties文件,而不管这个 stringbundle 元素是不是在别的 XUL 文件中已经定义过。当然,即使在不同 XUL 文件中,相同stringbunble 元素一般使用相同 id。
这时候实际上是定义了一组 stringbundle 元素集。它有类似下面这样的格式:
<stringbundleset id="stringbundleset">
  <stringbundle id="example-A" src="chrome://.../locale/01.properties" />
  <stringbundle id="example-B" src="chrome://.../locale/02.properties" />
  <stringbundle id="example-C" src="chrome://.../locale/03.properties" />
</stringbundleset>

回到 overlay.js 文件,添加如下两行代码,定义 strBundle 和 sayhello 两个变量,并用定义的变量“sayhello”替换原来在对话框中显示的那段文本。完成后保存文件。
var strBundle = document.getElementById("helloworld-strings");
var sayhello = strBundle.getString("SayHello_Confirm");

var bConfirmed = window.confirm(sayhello);
这两个变量的作用是: 首先通过 id 定位在 XUL 文件中定义的 stringbundle 元素,然后根据我们之前定义的标识名称到properties 文件中寻找需要显示的文本,由 getString 返回这些文本。这时候 confirm() 中 sayhello的值实际上就是引用的文本“Welcome to Hello World! Click OK tocontinue.”。这样,将来我们只需要翻译 properties 文件中的文本就可以很方便的实现 javascript 脚本文件的本地化。

另外,XUL 还提供了一个稍复杂的方法,用 getFormattedString 返回一组字符串或文本。这个方法在我们给的 HelloWorld 扩展中并没有遇到,所以这里只稍加叙述。
getFormattedString 的格式为:
getFormattedString("字符串名称", [字符串阵列])
例如,在 javascript 脚本中定义变量为:
var strBundle = document.getElementById("extension-strings");
var fileInfo = strBundle.getFormattedString("fileInformation", [fileName, fileSize]);
在 properties 文件中,文本定义为:
fileInformation=The file is called %1 and its size is %2.
其中 %1 和 %2 将依次替换为 fileName 和 fileSize 的值。

一般情况下,在一个扩展中你会碰到多个需要本地化的 javascript 脚本文件,你需要重复 (1) 到 (5)的步骤直到为每一个需要本地化的 javascript 脚本文件都创建一个对应的 properties 文件。同样,每组对应的javascript 脚本文件和 properties 文件除了文件扩展名不同,应该使用相同的主文件名。
  创建自己的 Bundle 你可能会觉得使用 XUL 提供的 stringbundle 元素,还要找到调用 javascript 脚本文件的 XUL 文件,然后在XUL 文件中定义 stringbundle 元素,这样太麻烦了。那么你也可以使用 nsIStringBundleService 模块在javascript 脚本文件中自己创建 Bundle。
首先,同样需要在 properties 文件添加如下一行代码:
SayHello_Confirm=Welcome to Hello World! Click OK to continue.
然后,在 overlay.js 文件里添加这样一段代码:
function TranslateString(strName)
{ var src = "chrome://helloworld/locale/overlay.properties";
  var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"]
   .getService(Components.interfaces.nsIStringBundleService);
  var Bundle = stringBundleService.createBundle(src);

  return Bundle.GetStringFromName(strName);
}
在这段代码中,我们不但创建了自己的 Bundle,还定义了一个 TranslateString() 函数。它们的作用是,首先getStringFromName 根据标识名称从 properties 文件中引用文本,然后用 TranslateString()返回这些文本。
现在用这个函数替换 overlay.js 中需要在用户界面显示的文本,并将函数的参数用文本的标识名称替换:
function helloWorld()
{
  var bConfirmed = window.confirm(TranslateString("SayHello_Confirm"));

  if(bConfirmed)
  {
    window.open("chrome://helloworld/content/","helloworld","chrome,centerscreen");
  }
}
这样,用这个简单的方法,我们同样也可以实现 javascript 脚本文件的本地化。

总结一下本地化的重要方法
在 locale 文件夹下,
每个以 ISO 语言代码(例如 en-US)命名的文件夹中就保存着所有可本地化的文本文件。
===========
XUL文件的本地化
* DTD (.dtd) 文件
DTD 文件用来定义实体,
包含由 XUL 文件引用的文本。
字符编码格式为: UTF-8,
并要求不写入 UTF-8 文件头标记(BOM)。
------------
把Entity看作是一个常量,它有一定的值。
引用Entity的时候,必须要在Entity名称前面加上“&&”符号,后面加上“;”符号。
------------
示例:占位
===========
脚本中文本的地化。
* properties (.properties) 文件
包含由 javascript 及其他脚本文件引用的文本。
字符编码格式为: Escaped Unicode (\uXXXX)
-----------------------------
使用 properties 文件和 String Bundles 来实现 javascript 脚本文件的本地化。
------------
示例:占位
JavaScript函数对象
1:声明式函数
//在加载页面时,只解析一次.随后无论参数的变化如何,调用次数多少:使用的都是同一个函数对象
语法:
function functionName(param1,...paramN){
      function statements;
}

2:匿名函数
//每次请求调用时,都解析(动态重构)
语法:
var variable = new Function("param1",..."paramN","function statements");

3:函数直接量/函数表达式
//同匿名函数类似,区别是:只解析一次
var variable = (param){
      function statements;
}

4:一次性对象的函数表现形式:
先看一下一次性对象(prototype采用的对象开发结构):
var variable = new Object(){
    variable.variA="Va1";
   variable.variB="Va2";
   variable.method = function(){
                                   return this.variA + variB;
                                   }
}

//我们也可以用旧函数来创建一个类似的对象,然后将其赋值给一个变量,并将其作为一次对象来使用
var variable = new function(){
     this.variA="Va1";
     this.variB="Va2";
     this.method=function(){
                                  return variA + variB;
                            }
}

生成器表达式
https://developer.mozilla.org/cn/New_in_JavaScript_1.8

这个新添加的特性,允许你简单的创建生成器(在JavaScript 1.7引入的)。通常你以前需要创建一个自定义的函数,它含有一个 yield,但是这个新特性使你可以使用类似数组概念的语法来创建一个独立的生成器句柄。
在 JavaScript 1.7 中,你可能需要写出想下面这样的代码来为一个对象创建自定义的生成器:
function add3(obj) {   for ( let i in obj )     yield i + 3; }  let it = add3(someObj); try {   while (true) {     document.write(it.next() + "<br>\n");   } } catch (err if err instanceof StopIteration) {   document.write("End of record.<br>\n"); }在 JavaScript 1.8 中,你可以规避要重建生成器函数的麻烦,而使用一个生成器表达式来代替:
let it = (i + 3 for (i in someObj)); try {   while (true) {     document.write(it.next() + "<br>\n");   } } catch (err if err instanceof StopIteration) {   document.write("End of record.<br>\n"); }生成器表达式也可以像数值那样被传给一个函数。非常值得注意的是,生成器在绝对必要的有用的时候才被运行(并不像典型的数组概念的条件那样,预先搭好数组的结构)。这个区别可以从下面的例子中看到:
使用JavaScript 1.7 数组理念
handleResults([ i for ( i in obj ) if ( i > 3 ) ]);  function handleResults( results ) {   for ( let i in results )     // ... }使用 JavaScript 1.8 的生成器表达式
handleResults( i for ( i in obj ) if ( i > 3 ) );  function handleResults( results ) {   for ( let i in results )     // ... }这两个例子之间最大的区别就是,使用生成器表达式的时候,只需要循环那个 'obj' 结构一次,总共;而在第一个例子中,将会在递归的时候再循环一次。

数组定义方式
var   myArray   =   new   Array(1,2,3,4,)   //普通方式  
  var   myArray   =   new   Array(20)   //20个元素  
  var   myArray   =   [1,2,3,4,5,6]   //数组直接量
JavaScript 1.6~1.8上的高级技巧
在jslibs的项目wiki上看到这些技巧,都是一些在mozilla spidermonkey javascript上的高级戏法。在JScript上不能用的哈~。这里转过来,很多技巧挺有趣的。
原文引用在:
http://code.google.com/p/jslibs/wiki/JavascriptTips
------------------------------------------
1.   destructuring assignments

JavaScript 1.7


var{a:x}={a:7};
Print(x);// prints: 7





2.   Generator Expressions


JavaScript 1.7


[ y for( y in[5,6,7,8,9])]// is [0,1,2,3,4]




and


[ y for each ( y in[5,6,7,8,9])]// is [5,6,7,8,9]




Because in for extracts index names, and for each extracts the values.


3.   Advanced use of iterators


JavaScript 1.8


Number.prototype.__iterator__ =function(){

for( let i =0; i <this; i++)
  yield i;
};
for( let i in5)
print(i);




prints:


1
2
3
4
5




This make Number object to act as a generator.


4.   Expression Closures


JavaScript 1.8


function(x) x * x;




Note that braces {...} and return are implicit


5.   Basic debugging


JavaScript 1.6


LoadModule('jsstd');
functionThrowAnError(){

  (function(){

    thrownewError("Whoops!");
  })();
}
try{

    ThrowAnError()
}catch(e){

    Print(e.stack);
}




prints:


Error("Whoops!")@:0
()@test.js:7
ThrowAnError()@test.js:5
@test.js:14





6.   Multiple-value returns


JavaScript 1.7


function f(){

  return[1,2];
}
var[a, b]= f();
Print( a +' '+ b );// prints: 1 2





7.   Operator [ ] and strings ( like charAt() )


JavaScript 1.6


var str ='foobar';
Print( str[4]);




prints:


a





8.   indexOf() and lastIndexOf() Works on Array


JavaScript 1.6


var obj ={};
var arr =['foo',567, obj,12.34];
Print( arr.indexOf(obj));// prints: 2





9.   Using Array functions on a non-Array object


JavaScript 1.7


var obj ={};
Array.push(obj,'foo');
Array.push(obj,123);
Array.push(obj,5.55);
Print( obj.toSource());// prints: ({0:"foo", length:3, 1:123, 2:5.55})





10.            Simulate threads using yield operator


JavaScript 1.7


var scheduler =newfunction(){

  var _workers =[];

  this.Add=function( worker ){

    _workers.push(new worker());
  }

  this.Run=function(){

    while( _workers.length )
      for each (var worker in _workers )
        try{
          worker.next();
        }catch(err if err instanceofStopIteration){
          _workers.splice( _workers.indexOf(worker),1);
        }
  }
}
function worker1(){

  for(var i =0; i <5; i++){

    Print('worker1: '+i,'\n');
    yield;
  }
}

scheduler.Add(worker1);
function worker2(){

  for(var i =0; i <10; i++){

    Print('worker2: '+i,'\n');
    yield;
  }
}

scheduler.Add(worker2);

scheduler.Run();




prints:


worker1:0
worker2:0
worker1:1
worker2:1
worker1:2
worker2:2
worker1:3
worker2:3
worker1:4
worker2:4
worker2:5
worker2:6
worker2:7
worker2:8
worker2:9





11.            swap two variables


JavaScript 1.7


var a =1;
var b =2;
[a,b]=[b,a];





12.            Destructuring assignment with function arguments


JavaScript 1.7


function foo([a,b]){

        Print(a);
        Print(b);
}

foo([12,34]);




Prints:


12
34





13.            JavaScript scope and LET instruction


JavaScript 1.7


var x =5;
var y =0;
let (x = x+10, y =12){
  Print(x+y);
}
Print(x+y);




prints:


27
5




or,


for( let i=0; i <10; i++){
  Print(i +' ');
}
Print(i);




prints:


0123456789 test.js:4:ReferenceError: i isnotdefined





14.            Iterate on values


JavaScript 1.6


for each (var i in[3,23,4])
        Print(i)




Prints:


3
23
4

chinastock_detail_getinfo
http://hq.sinajs.cn/format=js&list=sh600036,s_sh000001,s_sz399001,s_sz399106,s_sh000300

var hq_str_sh600036="招商银行,13.45,13.16,13.16,13.47,13.12,13.15,13.16,36584713,487881240,8000,13.15,24701,13.14,23279,13.13,53300,13.12,104200,13.11,16249,13.16,9100,13.17,50600,13.18,20500,13.19,9900,13.20,2008-12-15,11:35:58";
var hq_str_s_sh000001="上证指数,1962.598,8.383,0.43,459682,3135490";
var hq_str_s_sz399001="深证成指,7101.808,9.101,0.13,3601965,376566";
var hq_str_s_sz399106="深证综指,588.127,3.386,0.58,4274294440,1486010";
var hq_str_s_sh000300="沪深300,1973.973,13.593,0.69,280981,2304260";

被调用:chinastock_detail_getshtml
setTimeout(chinastock_detail_getinfo,20);

gZealChinaStock.m_ajaxRequest.responseText.split("\n").join("").split("\r").join("").split(';');
stockpattern = new RegExp('var hq_str_'+curStock.m_sFixid+'="([^"]+)";','g');

调用:
chinastock_detail_setstockinfo
    调用:
    chinastock_detail_setbigstock
        http://finance.sina.com.cn/realstock/company/sz399001/nc.shtml

对于gZealChinaStock对像的创建方式再作一点说明

引出一种类似与面向对象的设计模式

Crab = function(){//类的定义形式!!

this.leg = 10;//成员变量!!

//成员变量都写在这里
};


Crab.prototype = {

say : function(){alert('we hava '+this.leg+' legs');}

//成员方法都写这里
};


var
crabObj = new
Crab();


crabObj.say();

如果你以前玩过C++,那么一定非常熟悉了。这种类的定义方式是Ext的基础所在。
var crabObj = new Crab();其实执行了2个步骤!
第一:执行this.leg = 10,其结果就是crabObj.leg = 10
第二:将Crab.prototype这个对象给了crabObj,好比crabObj.say = Crab.prototype.say;
说白了,第一步交接成员变量,第二步交接成员方法。
还有些朋友喜欢这样定义类
function Crab(){
        this.leg = 10;
}
当然也是可以的
这就是最最普通的类的定义方式了。
======================
有了上面的基础,我们这一节来模拟一个简单的继承


Crab = function(){

this.leg = 10;
};


Crab.prototype.say = function(){alert('we hava '+this.leg+' legs')};


GenCrab = function(){//螃蟹进化成人,变成蟹将了,只有2条腿了

this.leg = 2;
}


function
extend(child,father){//定义出一个继承函数,有2个参数,子类,父类

child.prototype = father.prototype;
}


extend(GenCrab,Crab);//这样一来,蟹将也有say的方法了


gCrab = new
GenCrab();


gCrab.say();//执行出来 we hava 2 legs

怎么样,蟹将已经将螃蟹的方法继承下来了吧?那如果要将父类的属性也继承下来呢?我想到2个方法:
第一、把父类的属性写入prototype中,如Crab.prototype.leg = 10
第二、GenCrab.prototype = new Crab();不知道你能不能看懂,呵呵,估计网上都没有人这样用过,但这样子写能把属性和方法全部继承,其中的奥秘,请您自己思考下
好了,我们进入主题,怎么将属性继承下来的呢?
答案是第一种方法。如果您仔细看过我写的第一篇文章,您一定会说,规范约定,只有方法才写在prototype中的呀,怎么能把属性也写入呢?岂不是把清楚的事情又弄复杂了?
聪明的Ext团队,的的确确是用第一种方法的,只是在写法上稍稍改变了下

function
extend(child,father,override){//定义出一个继承函数,有2个参数,子类,父类,重载对象

child.prototype = father.prototype;



for(var
m
in
override){//将重载对象里面所有的东西(这里说的东西,无非就是属性和方法)都拿出来赋给子类,作为子类的属性或者方法

child.prototype[m] = override[m];

}
}

这样一来,又有了新的规范了,把类的属性都往override里面写,把方法仍旧往prototype里面写,我下面举个例子

function
extend(child,father,override){//定义出一个继承函数,有2个参数,子类,父类,重载对象

child.prototype = father.prototype;



for(var
m
in
override){//将重载对象里面所有的东西(这里说的东西,无非就是属性和方法)都拿出来赋给子类,作为子类的属性或者方法

child.prototype[m] = override[m];

}
}


Crab = function(){

//这里不写属性了
};


extend(Crab,Object,{leg:10,eye:2});//让Crab继承绝对父类Object,并把属性写到这里来,因为螃蟹和蟹将都有2只眼睛,所以蟹将一会将继承这个属性


Crab.prototype.say = function(){alert('we hava '+this.leg+' legs, '+this.eye+' eyes')};//方法仍旧在这里定义


GenCrab = function(){
}


extend(GenCrab,Crab,{leg:2});//这里,眼睛和脚都从父类那里继承过来了,但蟹将只有2只脚,所以我们只需要覆盖脚这个属性就可以了


gCrab = new
GenCrab();


gCrab.say();// we have 2 legs, 2 eyes

好了,属性和方法都已经可以继承了
========================
                源代码来分析


extend : function(){

// 内联函数,不懂?就是将这个方法编译后放入内存中

var
io = function(o){

for(var
m
in
o){

this[m] = o[m];

}

};

return
function(sb, sp, overrides){

if(typeof
sp == 'object'){//如果子类还不存在,只有父类和一些属性,那么就调用这2个参数,来构造一个子类,这里面的第三步非常神奇,很难解释的清楚,大致意思就是构造出这么匿名类,并将父类的构造方法借给它用用,嘿嘿,这么解释还不明白就留言吧

overrides = sp;

sp = sb;

sb = function(){sp.apply(this, arguments);};

}

var
F = function(){}, sbp, spp = sp.prototype;//sb代表子类,sbp代表子类prototype,sp代表父类,spp代表父类prototype

F.prototype = spp;

sbp = sb.prototype = new
F();//其实就是child.prototype = father.prototype,new F()看不懂看第二节

sbp.constructor=sb;//这2步一会儿细说

sb.superclass=spp;

if(spp.constructor == Object.prototype.constructor){//这个分支也不可以不管

spp.constructor=sp;

}

sb.override = function(o){//给子类赋予一个override方法

Ext.override(sb, o);

};

sbp.override = io;//给子类的对象赋予override方法

Ext.override(sb, overrides);//将overrides里面的东西,全部赋予子类的prototype里面,不懂看第二节

return
sb;//将这个全新包装的子类返回

};

}(),

我们来详细说说 sbp.constructor=sb 这个东东,为什么要写这么一步呢?因为child.prototype =father.prototype这步执行好后,会把child的constructor给抹掉,所以要把它重新指回来,那么为什么一定要配上这个constructor呢?网上有很多解释,但大都是一抄例子了事,搞了半天还是不明白有什么用处,其实constructor只是类的一个引用,当我们把一个对象调用来调用去,我们都忘记这个对象是由谁创建的时候,它就派上用场了,obj.constructor返回的就是创建obj的那个类了,明白了吧?其次,constructor还有一个方法就是反向调用,比如这样写obj.constructor.call(this),意思是用obj去调用obj的构造方法。恩恩……非常难理解,我打算后面的章节好好介绍它的用途。
sb.superclass=spp呢?superclass又是什么?这个是Ext无中生有的一个属性而已,让子类知道它的父类是谁而已,一个标记,呵呵
综上,三部曲已经出来了吧?
第一、将属性和方法都继承下来
第二、恢复constructor,建立superclass指针
第三、将子类的属性写入到子类里
看完这3节,我想你对Ext.extend不仅有了了解,而且应该体会到Ext的编码规范,通常定义一个类,有这个三步
第一:定义Child类
Child = function(){
}
第二:Ext.extend(Child,Father,{定义Child的属性})
第三:Child.prototyp = {定义Child的方法};
或者可以只用父类和属性直接构造子类
Child = Ext.extend(Father,{});
Ext更多用这个方法,并且将方法也写入{}里面,这个方法较之上面的,多了一个神奇的第三步,见上面的代码,期间的奥秘就在于,new Child()的时候,委托谁来构造,上面是Child自己来构造,而下面这种调用方式是委托Father来构造
您照着这样的思路去看源代码定会轻松不少的:)


收藏本文到网摘: 添加到“Google书签” 添加到“Yahoo收藏” 添加到“QQ书签” 添加到“百度搜藏” 添加到“新浪ViVi收藏夹” 添加到“Del.icio.us” 添加到“365天天网摘” 添加到“天极网摘” 添加到“POCO网摘” 添加到“和讯网摘” 添加到“Bolaa博客收录中心” 添加到“igooi网摘” 添加到“天下图摘”

作者:ping@随笔1987
地址:http://www.sb1987.cn/post/638/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明。

学习札记 | 评论(0) | 引用(0) | 阅读(1130)
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]