【Prototype 1.4.0】源码解读----全文注释版
http://www.cnblogs.com/me-sa/articles/605263.html

*  Prototype JavaScript framework, version 1.4.0
 
*  (c) 2005 Sam Stephenson <sam@conio.net>
 
*
 
*  Prototype is freely distributable under the terms of an MIT-style license.
 
*  For details, see the Prototype web site: http://prototype.conio.net/
 
 
*  这是一个JavaScript的框架,致力于简化动态的Web开发,完全按照面对对象的思想
 
*  进行Javascript开发,添加了迭代器的概念增强Javascript的设计能力。
 
*  Prototype框架构思独特充满了技巧性的代码,方便易用的工具类!
 
*
/*--------------------------------------------------------------------------*/
 
  
/* 【Prototype】定义一个全局对象,提供一个全局的基本信息和工具 */
var Prototype = {
  Version: '
1.4.0', //可以作为版本检测用
//
用于脚本检测的正则表达式,经常使用所以放在这里起到全局常量的作用
  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',

  emptyFunction: 
function() {},//空函数
  K: function(x) {return x}//K方法返回参数本身,在后面经常用到
}


/*========================================================================================*/

/*
 *【Class】对象的作用只有一个就是提供了一个定义类的模式
 * 仅含有create 一个方法,返回一个构造函数。 
 * 一般使用如下  
 *     var X = Class.create();  返回一个类型  
 * 要使用 X 类型,需继续用 new X()来获取一个实例 这与C# JAVA类似
 * 返回的构造函数会执行名为 initialize 的方法, initialize 是 Ruby 对象的构造器方法名字。 
 * 此时initialize方法还没有定义,其后的代码中创建新类型时会建立相应的同名方法,可以看作是一个抽象方法。 
 * 从C#角度讲可以理解为用Class.create()创建一个继承Object基类的类。 
 * 
 
*/
 

var Class = {
  create: 
function() {
    
return function() {  //下面使用Apply方法传递参数是一个常用的技巧
      this.initialize.apply(this, arguments);
    }

  }

}


/*========================================================================================*/


//Abstract是一个空对象,它的作用仅仅是作为一个抽象的命名空间,所有在该对象下定义的类都是抽象类
//
从而从形式上与实体类分开
var Abstract = new Object();

/*
 *Object是所有对象的基类,这个基类有两个静态方法
 
*/
 
//把Source的所有属性和方法传递给Destination,实现了继承的效果
Object.extend = function(destination, source) {
  
for (property in source) {
    destination[property] 
= source[property];
  }

  
return destination;
}

//观察Object的组成,需要参数中的object实现自己的inspect方法
Object.inspect = function(object) {
  
try {
    
if (object == undefined) return 'undefined';
    
if (object == nullreturn 'null';
    
return object.inspect ? object.inspect() : object.toString();
  }
 catch (e) {
    
if (e instanceof RangeError) return '';
    
throw e;
  }

}


/*========================================================================================*/


//【Function】是所有函数对象的基类,可以通过对它的扩展实现对所有函数对象添加功能
/* 这里在绑定的时候旧可以传递参数而不是调用的时候才指定参数,bind方法接收多个参数
  将函数绑定到第一个参数指定的对象上,并返回该方法的调用句柄
*/

Function.prototype.bind 
= function() {
  
// $A()方法的作用是把参数专为数组 
  //数组的shift方法作用是删除数组的第一个元素
  var __method = this, args = $A(arguments), object = args.shift();
  
return function() {
    
return __method.apply(object, args.concat($A(arguments)));
    
//这里的$A(arguments)是条用返回函数句柄时传递的参数,不是bind方法的参数
  }

}

/*
 * 和bind一样,不过这个方法一般用做html控件对象的事件处理。所以要传递event对象 
 * 好像是重载了_method方法
 
*/
 

Function.prototype.bindAsEventListener 
= function(object) {
  
var __method = this;
  
return function(event) {
    
return __method.call(object, event || window.event);
  }

}


/*========================================================================================*/

//【Function】是所有数值类型的基类

Object.extend(Number.prototype, 
{
  toColorPart: 
function() {           //RGB-》16进制颜色
    var digits = this.toString(16);
    
if (this < 16return '0+ digits;
    
return digits;
  }
,

  succ: 
function() //数值加一 var a=1; var b=a.succ; 那么b=2
    return this + 1;
  }
,

  times: 
function(iterator) 
  
//这里的参数iterator是一个迭代器作用就是循环调用指定次数的iterator函数
  //$R(start,end,exclusive)是创建ObjectRnge对象的快捷方式
    $R(0thistrue).each(iterator);
    
return this;
  }

}
);

/*========================================================================================*/

//提供了一个方法these,要求参数是函数的句柄,可以有多个。作用就是返回第一个成功执行的函数的返回值
var Try = {
  these: 
function() {
    
var returnValue;

    
for (var i = 0; i < arguments.length; i++{
      
var lambda = arguments[i];
      
try {
        returnValue 
= lambda();
        
break;
      }
 catch (e) {}
    }


    
return returnValue;
  }

}


/*========================================================================================*/

//定时器类用来实现Window.setInterval的效果,在给定时间间隔执行某一个函数,增加了对重复执行的控制S
var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype 
= {
  initialize: 
function(callback, frequency) {
  
//构造函数指定回调函数和执行频率,单位是秒
    this.callback = callback;
    
this.frequency = frequency;
    
this.currentlyExecuting = false;

    
this.registerCallback();
  }
,
  
/* 开始调用定时器,无需显示调用,在构造函数中就实现了自动调用,这一下面的
this.onTimerEvent.bind(this)如果写成this.onTimerEvent则this指针就会指向widows对象即setInterval的默认对象
从而不能正确的引用到下面两个函数上,也就失去了对正在执行函数的控制
*/


  registerCallback: 
function() {
    setInterval(
this.onTimerEvent.bind(this), this.frequency * 1000);
  }
,
//下面的函数相当于是回调函数的一个代理, setInterval是到了指定的时间就会强制执行而这里
//
加入了一个判断如果callback函数执行的时间超过了一个时间片,则阻止其被重复执行
  onTimerEvent: function() {
    
if (!this.currentlyExecuting) {
      
try {
        
this.currentlyExecuting = true;
        
this.callback();
      }
 finally {
        
this.currentlyExecuting = false;
      }

    }

  }

}
/*使用举例:
function GetOnlineCount()
{//获得在线人数
}
new PeriodicalExecuter(GetOnlineCount,10)每10秒获取一次
*/


/*========================================================================================*/
/* 框架核心内容--------【基础工具类】
/*========================================================================================
*/


 
/*document.getElementById(id)获取一个指定ID的结点,是这个方法的快捷方式和扩展
 可以指定多个参数返回一个对象数组。参数也不一定是ID也可以是对象本身的引用,例如
 $('id')等价于$($('id'))
  
*/

function $() {
  
var elements = new Array();

  
for (var i = 0; i < arguments.length; i++{
    
var element = arguments[i];
    
if (typeof element == 'string')
      element 
= document.getElementById(element);

    
if (arguments.length == 1)
      
return element;

    elements.push(element);
  }


  
return elements;
}


/*========================================================================================*/
//【String】类的扩展

//删除字符串中的HTML标记
Object.extend(String.prototype, {
  stripTags: 
function() {
    
return this.replace(/<\/?[^>]+>/gi, '');
  }
,
//删除字符串中的脚本块
  stripScripts: function() {
    
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  }
,
//提取字符串中的所有脚本块,作为数组返回,每一个脚本作为一个数组元素
  extractScripts: function() {
    
var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    
var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
    
return (this.match(matchAll) || []).map(function(scriptTag) {
      
return (scriptTag.match(matchOne) || ['', ''])[1];
    }
);
  }
,
//提取字符串中的脚本并执行
  evalScripts: function() {
    
return this.extractScripts().map(eval);
  }
,
//将字符串进行html编码例如"<" --》"&lt"
  escapeHTML: function() {
    
var div = document.createElement('div');
    
var text = document.createTextNode(this);
    div.appendChild(text);
    
return div.innerHTML;
  }
,
//对字符串进行html解码例如"&lt"--》"<"
  unescapeHTML: function() {
    
var div = document.createElement('div');
    div.innerHTML 
= this.stripTags();
    
return div.childNodes[0? div.childNodes[0].nodeValue : '';
  }
,
//将查询字符串格式的字符串转换为键值对数组
//
例如var s="a=1&b=2&c=3"; var s2=s.toQueryParams(); s2为{a:1,b:2,c:3}
  toQueryParams: function() {
    
var pairs = this.match(/^\??(.*)$/)[1].split('&');
    
return