-
s.charAt(i)
-
s.split("")[i]
在 IE7, Firefox3.6.8, Chrome5.0, Safari5.0, Opera10 上测试, 除了 Firefox 之外,所有的浏览器均是第 2 种表达式更快速。
s.charAt(i)
s.split("")[i]
在 IE7, Firefox3.6.8, Chrome5.0, Safari5.0, Opera10 上测试, 除了 Firefox 之外,所有的浏览器均是第 2 种表达式更快速。
if(true){会发现输出true,而且不论嵌套多深,也不论使用任何块级作用域进行嵌套,最后变量依然如同在调用处之前,而且同级的作用域中定义的一样;值为在此之前,在块级作用域中所做改变的结果。注意:如果块级作用域未被执行,则其中声明定义的变量会被声明(var name),但不被定义(即未被初始化,此时name为undefined,引用name时不抛异常)。
var bool=true;
}
document.write(bool); // output:true
if(false){var bool=true;}之前虽知道,IE里for(var i=0;...)里定义的i,在for之外也是可以使用的,但是现在才知道这种情况更为猖獗,大出我的意料之外,而更意外的是,IE 7(IE6?), Firefox 3(FF1,FF2?), Opera 9, Chrome 1, Safari 3表现均丝毫不差。
document.write(bool); // output:undefined
// Global Scope附B 测试结果(IE 7, FF 3, Opera 9, Safari 3, Chorme 1均同):
if (true){
var v10 = true;
}else {
var v00 = false;
}
document.write("v10 : "+v10+"<br />");
document.write("v00 : "+v00+"<br />");
document.write("<hr />");
// Function Scope
function functionScopes(){
if (true){
// 以下均执行
var v11 = true;
do{
var v12 = true;
}while (false);
while (true){
var v13 = true;
break;
}
switch (1){
case 1:
var v14 = true;
default:
var v15 = true;
}
try{
var v16 = true;
throw new Error("");
}catch(e){
var v17 = true;
}finally{
var v18 = true;
}
for (var v19=0; v19<1; v19++){
var v1a=true;
}
with(v11){
var v1b = true;
}
function inn1(){
var inn11 = false;
}
}else {
// 以下均未执行
var v01 = false;
do{
var v02 = false;
}while (false);
while (false){
var v03 = false;
}
try{
var v06 = true;
throw new Error("");
}catch(e){
var v07 = true;
}finally{
var v08 = true;
}
switch (1){
case 1:
var v04 = true;
default:
var v05 = false;
}
for (var v09=0; v09<1; v09++){
var v0a=true;
}
with(v01){
var v0b = true;
}
function inn0(){
var inn01 = false;
}
}
document.write("v11 : "+v11+"<br />");
document.write("v12 : "+v12+"<br />");
document.write("v13 : "+v13+"<br />");
document.write("v14 : "+v14+"<br />");
document.write("v15 : "+v15+"<br />");
document.write("v16 : "+v16+"<br />");
document.write("v17 : "+v17+"<br />");
document.write("v18 : "+v18+"<br />");
document.write("v19 : "+v19+"<br />");
document.write("v1a : "+v1a+"<br />");
document.write("v1b : "+v1b+"<br />");
document.write("<hr />");
document.write("v01 : "+v01+"<br />");
document.write("v02 : "+v02+"<br />");
document.write("v03 : "+v03+"<br />");
document.write("v04 : "+v04+"<br />");
document.write("v05 : "+v05+"<br />");
document.write("v06 : "+v06+"<br />");
document.write("v07 : "+v07+"<br />");
document.write("v08 : "+v08+"<br />");
document.write("v09 : "+v09+"<br />");
document.write("v0a : "+v0a+"<br />");
document.write("v0b : "+v0b+"<br />");
document.write("<hr />");
try{alert(inn11);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(inn01);}catch(e){document.write((e.message||e)+"<br />");}
}
functionScopes();
document.write("<hr />");
try{alert(v11);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v12);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v13);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v14);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v15);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v16);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v17);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v18);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v19);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v1a);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v1b);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v01);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v02);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v03);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v04);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v05);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v06);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v07);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v08);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v09);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v0a);}catch(e){document.write((e.message||e)+"<br />");}
try{alert(v0b);}catch(e){document.write((e.message||e)+"<br />");}
v10 : true
v00 : undefined
v11 : true
v12 : true
v13 : true
v14 : true
v15 : true
v16 : true
v17 : true
v18 : true
v19 : 1
v1a : true
v1b : true
v01 : undefined
v02 : undefined
v03 : undefined
v04 : undefined
v05 : undefined
v06 : undefined
v07 : undefined
v08 : undefined
v09 : undefined
v0a : undefined
v0b : undefined
'inn11' 未定义
'inn01' 未定义
'v11' 未定义
'v12' 未定义
'v13' 未定义
'v14' 未定义
'v15' 未定义
'v16' 未定义
'v17' 未定义
'v18' 未定义
'v19' 未定义
'v1a' 未定义
'v1b' 未定义
'v01' 未定义
'v02' 未定义
'v03' 未定义
'v04' 未定义
'v05' 未定义
'v06' 未定义
'v07' 未定义
'v08' 未定义
'v09' 未定义
'v0a' 未定义
'v0b' 未定义
String.prototype.trim = function(){为了避免正则表达式使用括号带来的消耗,可以写成这样,II:
return this.replace(/(^\s+)(\s+$)/g, '');
};
String.prototype.trim = function(){另外有一套实现是这样的,III:
return this.replace(/(?:^\s+)(?:\s+$)/g, '');
};
String.prototype.lTrim = function(){其实调用函数也会多少有一点消耗,写成这样或许会快一点点(开个玩笑,这样写会带来一些冗余代码,这时候就需要基于效率(时间)、代码量(空间)和可维护性方面的考量了),IV:
return this.replace(/^\s+/, '');
};
String.prototype.rTrim = function(){
return this.replace(/\s+$/, '');
};
String.prototype.trim = function(){
return this.lTrim().rTrim();
};
String.prototype.trim = function(){后来我对正则表达式有了更多的了解,知道了贪婪与非贪婪匹配,于是自作聪明写了这一段:
return this.replace(/^\s+/, '').replace(/\s+$/, '');
};
String.prototype.trim = function(){我曾经为这段代码自鸣得意了好长一段时间,不过后来想到点号不包括换行符,字符串中间有换行符时,返回值就不正确了,于是不情愿的改成这样(多行模式效率也很低),V:
return this.replace(/^\s*(.*?)\s*$/, "$1"); // 两端空白字符贪婪匹配,中间字符非贪婪匹配。
};
String.prototype.trim = function(){谁知,这样的代码遇到大家伙时效率会一落千丈,哎,失败。
return this.replace(/^\s*((?:.\n)*?)\s*$/, "$1");
};
String.prototype.trim = function(){而最土的方法,莫过于两头都使用循环获得索引了,VII:
var l=this.length;
/^[\s]*/.test(this);
// /(?=[^\s])/.test(this);// -- never-online
var s = RegExp.lastIndex;
if(1==s && !Char.isBlank(this.charAt(0)))s=0;
if(s==l){return '';}
// /\s*$/.test(this);
// var e=RegExp.index;
var e=$lastIndexOf(function(c){return !Char.isBlank(c);});
e=-1==e?l:e+1;
return this.substring(s,e);
};
String.prototype.trim = function(){
var f=function(c){return !Char.isBlank(c);};
var l=this.length, s=this.$indexOf(f), e=this.$lastIndexOf(f);
if(-1==s)s=0;
e= -1==e?l:e+1;
return this.substring(s, e);
};
String.prototype.$indexOf = function(f){
for(var i=0,c,l=this.length; i=0; i--){
c=this.charAt(i);
if(f(c)){return i;}
}
return -1;
};
String.prototype.$lastIndexOf = function(f){
for(var i=this.length-1,c; i>=0; i--){
c=this.charAt(i);
if(f(c)){return i;}
}
return -1;
};
var Char = {到了永不在线(Google Translate翻译为“永远在线”)的算法,VIII:
isBlank:function(c){
//return /\s/.test(c);
return ' '==c '\t'==c '\r\n'==c '\n'==c '\r'==c;
}
};
String.prototype.trim = function(){最初这个算法让我很兴奋,直觉上,感觉这样效率肯定要高,不过事实并不是这么简单。
var s = this.replace(/^\s+/, '');
var l=s.length, e=l;
if(0==l){return '';}
for(var i=l-1; i>=0; i--){
if(!Char.isBlank(s.charAt(i))){
e=i+1;
break;
}
}
return this.substring(0,e);
};
String.prototype.bytes = function(){这里判断字符是否双字节有很多方法,效率较高的之间相差(大概)不大。
var l=this.length, r=l, n=0xff;
for(var i=l; i>=0; i--){
if(this.charCodeAt(i)>n){
r++;
}
}
return r;
};
String.prototype.bytes = function(){多动脑子,则想法愈多(也常把简单的事情复杂化),我想如果可以快速取得表达式(双字节/单字节)匹配次数,两值相加应该比较高效,III:
return this.replace(/[^\x00-\xff]/g,"xx").length;
};
String.prototype.bytes = function(){IV:
return this.length+this.replace(/[\x00-\xff]/g,"").length;
};
String.prototype.bytes = function(){另外看到梅花雪用数组能提供字符串拼接速度,也想:把字符串split为数组,不想对大型字符串而言,这split一步就慢得不行。
return this.length+(this.match(/[^\x00-\xff]/g)"").length;
};
If the element can't be scrolled (e.g. it has no overflow), scrollLeft is set to 0.对于一些不可滚动(scroll,即没有溢出)的元素,scrollLeft始终为0。而单行文本框(在Gecko引擎看来)是不可滚动的,即使将样式指定为overflow:scroll(IE会出现水平和垂直滚动条这样的怪胎)。
甚至《代码大全》的作者有这样一句话:如果为我工作的程序员用递归去计算阶乘,那么我宁愿换人。作者对递归的态度相当谨慎,这在静态命令式语言中显然是正确的,但是在函数式语言中,由于有尾递归优化的存在,递归反而是最自然的形式,况且我打心里认为递归更符合人类思维。(by dennis)
function recursion(n){return n==1?1:n*recursion(n-1);}
function tailRecursion(n, a){a = a||1; // 尾递归之尾,即上次递归结果。return n==1?a:tailRecursion(n-1, a*n);}
Math.factorial_III = function(n){
var a = arguments[1]||1;
return n<=1?a:Math.factorial_III(n-1, a*n);
};
/**
* 连接两个正则表达式。
* 题外话:获得字符串常量""的长度,比构建空数组再求其长度效率高(忽略构建过程,求长度消耗时间相同)。
* @param {RegExp} r 指定被连接的正则表达式对象。
* @param {String} p 连接后的表达式使用的选项,由"i","g","m"组合而成。
* @return {RegExp} 返回连接后的正则表达式。
*/
RegExp.prototype.concat = function(r, p){
var i=(this.source.match(/\((?!\?:)/g) || "").length; // 正向预搜索。
return new RegExp(this.source+r.source.replace(/\\(\d)/g, function($0, $1){
return "\\" + (i+($1 | 0)); // 修正第二个表达式中的反向引用。注意这里的位运算。
}), p);
};
一万次循环叠加可以发现构建空字符串比构建空数组求长度快1到3倍。var I = 10000;
var d = new Date();
for (var i=0; i<I; i++){
"".length;
}
d = new Date()-d;
var d2 = new Date();
for (var i=0; i<I; i++){
[].length;
}
d2 = new Date()-d2;document.write(d+":"+d2);
可以发现,求空字符串长度与空数组长度的过程效率相当。可见,代码II处空数组效率多余的消耗主要在构建空数组对象上。var I = 10000;
var s="";
var d = new Date();
for (var i=0; i<I; i++){
s.length;
}
d = new Date()-d;var a=[];
var d2 = new Date();
for (var i=0; i<I; i++){
a.length;
}
d2 = new Date()-d2;document.write(d+":"+d2);
/**
* 求阶乘的改进算法。
* 循环求积次数减少一半,但是求平方时增加开销,在IE6,Firefox2,Safari3下测试求170的阶乘
* (大于170的阶乘结果为Infinity,没有实际意义)均比简单求积方法少不到10毫秒。
* 求小于50的阶乘的效率表现有时不如直接使用简单的累乘方法。
* @param {Number, Integer} n 求阶乘的目标整数。
* @see <a href=" http://www.matrix67.com/blog/article.asp?id=442">计算阶乘的另一些有趣的算法</a>,
* <a href=" http://www.luschny.de/math/factorial/index.html">巨牛,20多种阶乘算法的代码</a>
*/
Math.factorial_II = function(n){
if (n===0){return 1;}
if (!n.isPositiveInteger()){throw new Error("param error.")}
var m=(n.isOdd()?(n+1):n)/2; // middle number.
var r = n.isOdd()?m:m*n; //result;
for (var i=1; i<m; i++){
//r*=(Math.pow(m,2) - Math.pow(i,2)); // Math.pow方法求平方比两个数直接相乘的效率低很多。
r*=(m*m - i*i);
}
return r;
};/**
* 判断当前数值对象是否是整数。
* @return {Boolean} true,如果数值是整数,否则返回false。
*/
Number.prototype.isInteger = function(){
return /^[+-]?\d+$/.test(this);
};/**
* 判断数值是否是为负数。
* @return {Boolean} true,如果数值是负数,否则返回false。
*/
Number.prototype.isNegative = function(){
return this<0;
};/**
* 判断数值是否为负整数。
* @return {Boolean} true,如果数值为负整数,否则返回false。
*/
Number.prototype.isNegativeInteger = function(){
return this.isNegative() && this.isInteger();
};/**
* 判断当前数字的值是否为奇数(定义:不能被2整除的(整)数,如1,3和5)。
* 关于零(0)是否属于偶数,目前似乎尚无定论,这里不予理会,作为偶数处理。
* @return {Boolean} true,如果当前值是奇数,否则,返回false。
*/
Number.prototype.isOdd = function(){
/* Javascript整除(取模)运算:
* 被除数为正整数时,结果为0或1;
* 为负整数时,结果为0或-1;
* 为0时,结果为0;
* 为小数时,结果为正或负小数。
*/
return this.isInteger() && ((this%2)!==0);
};
不管因为什么原因,不给一个应用程序建立文档都不是一件好事,即使建立文档的工作一般令人厌烦。在给客户端JavaScript建立文档时尤其如此;与服务器端技术相比,客户端JavaScript通常被人们认为是前者的一个丑陋的继子。有趣的是,JavaScript文档问题的解决办法却来自一个非常相似的服务器端技术――Java。
有一个非常简洁的工具叫做Javadoc,可帮助Java开发者生成文档。这个工具还有一个JavaScript版本―― JSDoc,它可用于开发HTML文档,不仅帮助你给代码建立文档,而且有助于预防一些问题,如几个函数或对象基本上实现相同的功能,以及缺乏一般性的库知识。本教程将为你说明如何安装和使用JSDoc,以给JavaScript创建文档。
安装JSDoc
遗憾的是,安装JSDoc并不十分简单。这主要是因为它是用Perl编写的,因此除非你已经安装了Perl,否则就需要一两个额外的步骤。由于我最近在笔记本电脑上安装了Windows XP Pro,我自己就经历过这些额外的步骤。首先我必须下载和安装 ActivePerl,它是一个msi文件。图A显示了一部分安装过程[图略]。(注:双击运行msi文件,使用默认设置即可)成功安装ActivePerl后,接下来就要下载和解压JSDoc。这时,你可能会在一个DOS窗口中运行JSDoc,但如果你这样做,它可能无法运行。这是因为你缺少一个Perl软件包,如图B所示[图略](注:错误提示为Can't locate HTML/Template.pm in @INC ..... )。幸运的是,你可以在同一个窗口中输入ppm调用Perl软件包管理器,如图C所示[图略]。
使用Perl软件包管理器,你就可以安装缺少的HTML-模板软件包,如图D所示。[图略](注:点击工具栏View All packages[Ctr+1]按钮,在搜索框输入HTML-Template,选中列表中的HTML-Template项,如果它前面的图标是灰色的,右键并点击出现的唯一菜单项 Install HTML-Template安装,也可以标记然后安装)
(又注:网上有"在Dos窗口输入ppm命令,然后
PPM> install HTML-Template
PPM> quit "的做法,不过我下载的1.10.2版输入ppm就会弹出软件包管理器,命令行不可输入)使用JSDoc
表中列出了一些你可以在JavaScript文档中使用的标签。
标签 描述
@addon
把一个函数标记为另一个函数的扩张,另一个函数的定义不在源文件中。
@argument
用大括号中的自变量类型描述一个自变量。
@author
函数/类作者的姓名。
@base
如果类是继承得来,定义提供的类名称。
@class
用来给一个类提供描述,不能用于构造器的文档中。
@constructor
描述一个类的构造器。
@deprecated
表示函数/类已被忽略。
@exception
描述函数/类产生的一个错误。
@exec
@extends
表示派生出当前类的另一个类。
@fileoverview
表示文档块将用于描述当前文件。这个标签应该放在其它任何标签之前。
@final
指出函数/类。
@ignore
让JSDoc忽视随后的代码。
@link
类似于@link标签,用于连接许多其它页面。
@member
定义随后的函数为提供的类名称的一个成员。
@param
用大括号中的参数类型描述一个参数。
@private
表示函数/类为私有,不应包含在生成的文档中。
@requires
表示需要另一个函数/类。
@return
描述一个函数的返回值。
@returns
描述一个函数的返回值。
@see
连接到另一个函数/类。
@throws
描述函数/类可能产生的错误。
@type
指定函数/成员的返回类型。
@version
函数/类的版本号。
除上面提供的信息外,在JSDoc.pl命令后增加-h或-help选项,就会显示在生成文档时可以使用的选项列表。图G显示的是使用帮助选项的结果。
命令行进入JsDoc根目录,输入命令:
> perl jsdoc.pl test.js tes2.js
默认安装perl会设置将perl安装路径放入系统环境变量,这样你可以在任意路径中使用perl命令。如果你想在任意目录找到jsdoc.pl,可以将jsdoc安装目录设置到系统环境变量中。可以批量为javascript源代码生成文档。
乱码问题
默认情况下生成中文文档会出现乱码,如果你查看文档源代码就会发现,源代码本没有乱码,你只需要在JSDoc文档模板(根目录下所有的tmpl文件,有的版本可能在JSDoc子目录下)头部加上META标记并重新生成文档即可。
<meta http-equiv="content-type" content="text/html; charset=gb2312" />
其中粗体gb2312可以换成Big5,UTF-8之类,请设置为与javascript源代码文件编码格式相同。
see http://caterpillar.onlyfun.net/GossipCN/AjaxGossip/JSDocBig5.html
集成到Editplus
Javascript 数据类型分为值类型和引用类型,其中值类型包括字符串实体(例如:"string" ),数值实体(例如:100 )和布尔值实体(如:true )。而其他的复杂类型都属于引用类型,例如日期型( new Date() ),正则表达式(/a/gi, new RegExp("a", "gi") )数组( [1,2,3], new Array() )函数(function(){}, new Function() )和对象({a:"a", b:100}, new Object() )。这些都是Javascript 固有的数据类型,而用户自定义类型都属于引用类型(如:var Person = function(name){this.name=name;}; ),它们都只能使用new 关键字实例化为具体对象(new Person("hotoo") )。
为了理解Javascript 对象的类型,我们来看一些如下代码:
// test instanceof and typeof:
var instStr = ['"string"', '100' , 'true', '/a/g' , '[1,2,3]' , 'function(){}', '{}', 'null', 'undefined' ];
var inst = ["string", 100, true, /a/g, [1 ,2,3 ], function (){}, {}, null, undefined];
var ObjsStr = ["String", "Number" , "Boolean", "RegExp" , "Array", "Function", "Date" , "Object"];
var Objs = [String, Number , Boolean, RegExp, Array, Function, Date, Object];
jsoutInst ( "instanceof" , ObjsStr, Objs , instStr, inst);
function jsoutInst (methodName, tsStr , ts , osStr, os ){
document.write ("<table border='1'><tr>" );
document.write ("<td><strong>" +methodName+ "</strong></td>" );
for (var i= 0; i< tsStr. length; i++){
document.write ("<td>" +tsStr[i ]+"</td>" );
}
document.write ("</tr>" );
for (var i= 0; i< os. length; i++){
document.write ("<tr><td>" +osStr[i ]+"</td>" );
for (var j= 0; j< ts. length; j ++){
document.write ("<td>" +(os[i ] instanceof ts[j]? "<strong>true</strong>" :"false")+"</td>" );
}
document.write ("</tr>" );
}
document.write ("</table><br />" );
}
var typesStr = ["string", "number" , "boolean", "array" , "function", "date", "object" , "undefined"];
jsoutType ( "typeof" , typesStr, instStr , inst);
function jsoutType (methodName, tsStr , osStr , os){
document.write ("<table border='1'><tr>" );
document.write ("<td><strong>" +methodName+ "</strong></td>" );
for (var i= 0; i< tsStr. length; i++){
document.write ("<td>" +tsStr[i ]+"</td>" );
}
document.write ("</tr>" );
for (var i= 0; i< os. length; i++){
document.write ("<tr><td>" +osStr[i ]+"</td>" );
for (var j= 0; j< tsStr. length; j ++){
document.write ("<td>" +(typeof os[ i] == tsStr[ j]?"<strong>true</strong>" :"false" )+"</td>" );
}
document.write ("</tr>" );
}
document.write ("</table><br />" );
}
上面的代码很简单,第一个函数判断对象实例是否是某个类的实例(instanceof ),第二个函数对比对象实例是否与某类型(typeof )相等,他们将输出两个表格,我们来对比一下(为了方便阅读,这里将说明插在相应表格下。 )。
instanceof String Number Boolean RegExp Array Function Date Object "string" false false false false false false false false 100 false false false false false false false false true false false false false false false false false /a/g false false false true false false false true [1,2,3] false false false false true false false true function(){} false false false false false true false true {} false false false false false false false true null false false false false false false false false undefined false false false false false false false false
通过(instanceof )这个表格可以看出,值类型( "string", 100, true 等)不是任何对象的实体(instance ),而引用类型(/a/g, [1,2,3], function(){} 和 {} )既是本身类型的实体,又是其父类型的实体(所有类型都继承自Object 类型)。
所有通过引用类型(包括值类型的wrapper 类String, Number 和 Boolean )new 出来的对象,都是其对应类和其父类(这里是Object )的实例。
虽然值类型不是其对应wrapper 类的实例,但是值类型却可以直接使用其wrapper 类的属性和方法,就如同值类型是其 wrapper 类的实例一样。例如:"ABC".toLowerCase() 。
typeof | string | number | boolean | array | function | date | object | undefined |
"string" | true | false | false | false | false | false | false | false |
100 | false | true | false | false | false | false | false | false |
true | false | false | true | false | false | false | false | false |
/a/g | false | false | false | false | false | false | true | false |
[1,2,3] | false | false | false | false | false | false | true | false |
function(){} | false | false | false | false | true | false | false | false |
{} | false | false | false | false | false | false | true | false |
null | false | false | false | false | false | false | true | false |
undefined | false | false | false | false | false | false | false | true |
Keep It Simple, Stupid. (保持简单,保持朴拙。)
"a,b",c
("a)(b")(c)我们该如何选择?
("a,b")(c)
"a,b",c"
",a,b,",c,"
(a,b),c
You Can't Write Perfect Software. (你不可能写出完美的软件。)由于允许输入特殊符号本身,和用特殊符号来分词本身就很矛盾和复杂。而一个Javascript控件,一个帮助工具,没有必要做成无所不能。提供的功能越多,所受的制约就越多。
1. 帮助类只帮助;2. 让服务器去万能。
捕获需要自动完成的关键字;所以可以定义一个抽象的自动完成类,其他自动完成实例可以从这个抽象类继承,各个实例通过覆写抽象类的方法来完成自动完成工作。
与候选匹配项进行匹配;
返回并呈现匹配结果;
用户使用更方便的方法选中返回的候选匹配选项
自动完成替换,自动完成功能结束。
var Character = function(character){ // 单个字符类
if (character.length != 1){
throw Error("[Error:Arguments error.\nclass:org.xianyun.Character]");
}
this.value = character; // private:
this.charCode = character.charCodeAt(0); // public:readonly.
};
Character.reverseCase = function(character){ // 单个字符大小写反转,静态方法。
var charCode = character.charCodeAt(0);
if (charCode>=65 && charCode<=90){ // A-Z
return String.fromCharCode(charCode + 32);
}else if(charCode>=97 && charCode<=122){ // a-z
return String.fromCharCode(charCode - 32);
}else {
return character;
}
};
Character.prototype.reverseCase = function(){ // 单个字符大小写反转,成员方法。
return Character.reverseCase(this.value);
};
String.prototype.reverse = function(){ // 字符串顺序反转。
var s = "";
for (var i=this.length-1; i>=0; i--){
s += this.charAt(i);
}
return s;
};String.prototype.reverseCase = function(){ // 字符串大小写反转
var s = "";
for (var i=0; i<this.length; i++){
s += Character.reverseCase(this.charAt(i));
//s += new Character(this.charAt(i)).reverseCase();
}
return s;
};
通过算法控制,已经得到一定程度的解决。
var booleanObj1= new Boolean( false);
var booleanObj2 = new Boolean(booleanObj1);
document.write("The booleanObj2 value is " + booleanObj2);
过年了,同事们着急着买火车票,网上查询之,欲让结果固定时间后自动刷新,以便及时获得最新消息。
得如下代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Auto Refresh</title>
<meta name="Generator" content="EditPlus">
<meta name="Author" content="闲耘">
<meta name="Keywords" content="">
<meta name="Description" content="">
</head>
<body style="margin:0 0 0 0;">
<iframe id="piao" src="http://www.xianyun.org/" style="width:100%;height:100%;border:0px;frame-border:0px;margin-width:0px;margin-height:0px;"></iframe>
<script language="JavaScript">
<!--
var AutoRefresh = {
iframe : document.getElementById('piao'),
delay : 60*1000,
timer : null
};
AutoRefresh.refresh = function(){
this.iframe.src = this.iframe.src;
};
AutoRefresh.start = function(){
this.timer = setInterval('AutoRefresh.refresh();', this.delay);
};
AutoRefresh.stop = function(){
clearInterval(this.timer);
this.timer = null;
};
AutoRefresh.start();
//-->
</script>
</body>
</html>
var Module = function(){
this.currentName = '';
this.previousName = '';
this.show = function(module){
if (this.currentName == module){return;};
try{
this[this.currentName].deconstruction();
}catch (e){};
try{
this[module].construction();
}catch (e){};
this.previousName = this.currentName;
this.currentName = module;
};
this.showPrevious = function(){
try{
this[this.currentName].showPreviousModule();
}catch (e){};
};
this.showNext = function(){
try{
this[this.currentName].showNextModule();
}catch (e){};
setTimeout('this.focus()', 10);
};
this.$new = function(){
try{
this[this.currentName].$new();
}catch (e){};
};
this.edit = function(){
try{
this[this.currentName].edit();
}catch (e){};
};
this.$delete = function(){
try{
this[this.currentName].$delete();
}catch (e){};
};
this.refresh = function(){
try{
this[this.currentName].refresh();
}catch (e){};
};
this.search = function(){
try{
this[this.currentName].search();
}catch (e){};
};
this.help = function(){
try{
this[this.currentName].help();
}catch (e){};
};
};
// Demo:
var HTBlog = new Module();
HTBlog.currentName = 'ArticleList';
HTBlog.ArticleList = new Object();
HTBlog.ArticleList.construction = function(){
$('moduleArticleList').style.display = '';
HTBlog.ArticleList.setStyle('on');
HTBlog.ArticleList.setButton();
HTBlog.ArticleList.setTitle();
};
HTBlog.ArticleList.deconstruction = function(){
HTBlog.ArticleList.setStyle('off');
$('moduleArticleList').style.display = 'none';
};
HTBlog.Article = new Object();
HTBlog.Article.construction = function(){
$('moduleArticle').style.display = '';
};
HTBlog.Article.deconstruction = function(){
$('moduleArticle').style.display = 'none';
};
// ...