`

Prototype1.5.1.1代码注释(一)

阅读更多

本着学习的目的添加的注释,本人js水平很差,有不对的地方请各位一定多多指教。

 

/*  Prototype JavaScript framework, version 1.5.1.1
 *  (c) 2005-2007 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://www.prototypejs.org/
 *
/*--------------------------------------------------------------------------*/

/*一个新建对象,包含当前Prototype的版本以及当前浏览器信息*/
var Prototype = {
  Version: '1.5.1.1',

/*这个方法用的很巧,将一个NaN或者undefined对象通过两次!运算,得到false*/
  Browser: {
    IE:     !!(window.attachEvent && !window.opera),
    Opera:  !!window.opera,
    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
  },

/*IE6.0和Firefox2.0都不支持XPath*/
/*IE6.0不支持ElementExtensions,Firefox则支持*/
  BrowserFeatures: {
    XPath: !!document.evaluate,
    ElementExtensions: !!window.HTMLElement,
    SpecificElementExtensions:
      (document.createElement('div').__proto__ !==
       document.createElement('form').__proto__)
  },

/*正则,用来抽取出页面上用<script ...> ... </script>标记的代码段*/
  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

/*定义一个空函数*/
  emptyFunction: function() { },
/*暂时不明白定义这个函数的用意*/
  K: function(x) { return x }
}

/*定义了一个对象Class,抵用Class.create会返回一个function,返回的function代码为
function() {
	this.initialize.apply(this.arguments);
}
当调用返回的这个function或者使用new关键字的时候会调用function中定义的initialize方法
*/
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

/*定义了一个方法叫做extend,意思是把source中的属性,函数等都复制到destination这个对象里面去,
有点儿ruby中mixin的味道*/
Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
}

/*
给Object类新增加一个新的类方法,名叫inspect
用法Object.inspect(obj);
输出为一个字符串,代表obj的类新名称
*/
Object.extend(Object, {
  inspect: function(object) {
    try {
      if (object === undefined) return 'undefined';
      if (object === null) return 'null';
/*object.inspect?  意思是如果object定义了inspect方法,则执行inspect
和ruby中的duck type有异曲同工之妙,只不过js中更加直接,不需要ruby中的respond_to?了*/
      return object.inspect ? object.inspect() : object.toString();
    } catch (e) {
      if (e instanceof RangeError) return '...';
      throw e;
    }
  },

  toJSON: function(object) {
    var type = typeof object;
    switch(type) {
      case 'undefined':
      case 'function':
      case 'unknown': return;
      case 'boolean': return object.toString();
    }
    if (object === null) return 'null';
    if (object.toJSON) return object.toJSON();
    if (object.ownerDocument === document) return;
    var results = [];
    for (var property in object) {
      var value = Object.toJSON(object[property]);
      if (value !== undefined)
        results.push(property.toJSON() + ': ' + value);
    }
    return '{' + results.join(', ') + '}';
  },

/*把对象当哈希使唤。。。
当然js中这是再常用不过的了*/
  keys: function(object) {
    var keys = [];
    for (var property in object)
      keys.push(property);
    return keys;
  },

  values: function(object) {
    var values = [];
    for (var property in object)
      values.push(object[property]);
    return values;
  },

/*建立对象的浅拷贝,仅仅复制字段和引用*/
  clone: function(object) {
    return Object.extend({}, object);
  }
});

/*给function添加一个bind方法,以便把某个方法的执行绑定到一个对象上,也就是说在一个指定对象的上下文中执行本方法*/
Function.prototype.bind = function() {
/*注意此处__method变量和this的用法,这是为了避免this指向错误的上下文环境*/
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

/*把function绑定到一个对象上作为事件处理函数*/
Function.prototype.bindAsEventListener = function(object) {
  var __method = this, args = $A(arguments), object = args.shift();
  return function(event) {
/*为了兼容IE,使用[event || window.event]*/
    return __method.apply(object, [event || window.event].concat(args));
  }
}

/*为数值类型增加了
toColorPart,
succ,
times,
toPaddedString,
toJSON
方法*/
Object.extend(Number.prototype, {
  toColorPart: function() {
    return this.toPaddedString(2, 16);
  },

  succ: function() {
    return this + 1;
  },

  times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
  },

  toPaddedString: function(length, radix) {
    var string = this.toString(radix || 10);
    return '0'.times(length - string.length) + string;
  },

  toJSON: function() {
    return isFinite(this) ? this.toString() : 'null';
  }
});

/*为日期类型增加toJSON方法*/
Date.prototype.toJSON = function() {
  return '"' + this.getFullYear() + '-' +
    (this.getMonth() + 1).toPaddedString(2) + '-' +
    this.getDate().toPaddedString(2) + 'T' +
    this.getHours().toPaddedString(2) + ':' +
    this.getMinutes().toPaddedString(2) + ':' +
    this.getSeconds().toPaddedString(2) + '"';
};

/*Try.these(meth1,meth2,meth3...)
会依次尝试执行meth1,meth2,meth3....,第一个成功执行的方法的结果被返回,剩下的方法不再执行*/
var Try = {
  these: function() {
    var returnValue;

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

    return returnValue;
  }
}

/*--------------------------------------------------------------------------*/
/*一个定时器*/
/*usage: 
var timer = new PeriodicalExecuter(callback_function, frequency)
顾名思义,第一个参数是定时器的回调函数,第二个参数是时间间隔,生成定时器的实例后,定时器自动开始执行
timer.registerCallback; //启动定时器
timer.stop; //终止定时器
*/
var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
/*这里暂时不太理解,为什么callback要加上一个this参数?*/
        this.callback(this);
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}

/*给String类增加了一个类方法interpret和一个静态哈希specialChar*/
Object.extend(String, {
  interpret: function(value) {
/*String(value)相当于value.toString(); */
    return value == null ? '' : String(value);
  },
/*一些转义字符*/
  specialChar: {
    '\b': '\\b',
    '\t': '\\t',
    '\n': '\\n',
    '\f': '\\f',
    '\r': '\\r',
    '\\': '\\\\'
  }
});

/*String类的实例增加一些方法*/
/*
gsub,
sub,
scan,
truncate,
strip,
stripTags,
*/
Object.extend(String.prototype, {
/*gsub方法,replacement参数可以是一方法,也可是一个元素*/
/*usage:
  var str = somestring;
  str.gsub(param1,param2);
  其中params是用来匹配的字符串,也可是一个正则表达式,param2可以是一个用来替换的字符串,也可以是一个方法,这个方法一般定义为
  function(match){...}
  match为每一个匹配到的子字符串,在函数内部可以对子字符串进行处理,然后返回处理后的结果,举一个实际例子:
  var str = "hello world!";
  alert(str.gsub("o",function(match){ return match[0].succ(); } )); 
  弹出窗口显示"hellp,wprld!"
*/
  gsub: function(pattern, replacement) {
    var result = '', source = this, match;
/*假如某个字符串变量str调用了gsub方法,则在此会调用str的prepareReplacement方法
此方法接收gsub的replacement变量作为参数*/
    replacement = arguments.callee.prepareReplacement(replacement);
/*source就是调用gsub方法的字符串对象本身*/
    while (source.length > 0) {
/*调用match方法进行匹配,找到第一个匹配的对象*/
      if (match = source.match(pattern)) {
/*截取开头到匹配位置的字符串,添加到result中*/
        result += source.slice(0, match.index);
/*替换匹配的字符串,然后加到result结尾*/
        result += String.interpret(replacement(match));
/*删除第一个被匹配元素以及之前的部分,进行下一个循环*/
        source  = source.slice(match.index + match[0].length);
      } else {
        result += source, source = '';
      }
    }
    return result;
  },

/*同gsub类似*/
/*只替换前count个匹配对象*/
  sub: function(pattern, replacement, count) {
    replacement = this.gsub.prepareReplacement(replacement);
    count = count === undefined ? 1 : count;

    return this.gsub(pattern, function(match) {
      if (--count < 0) return match[0];
      return replacement(match);
    });
  },

/*找到所有匹配对象,在每个对象上执行iterator中定义的方法*/
  scan: function(pattern, iterator) {
    this.gsub(pattern, iterator);
    return this;
  },

/*截断函数,如果没有定义length就默认截断长度为30,没有定义truncation就默认为...*/
/*usage:
var str = "hello world";
str.truncate(7,"..");
此时str的内容变为"hello.."
注意它直接修改了当前字符串对象的内容
truncate的长度也计算到了length中
*/
  truncate: function(length, truncation) {
    length = length || 30;
    truncation = truncation === undefined ? '...' : truncation;
    return this.length > length ?
      this.slice(0, length - truncation.length) + truncation : this;
  },

/*去掉字符串开头和结尾的空格*/
  strip: function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  },

/*去除所有<xxxx>和</xxxx>这样的字符串*/
  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(function(script) { return eval(script) });
  },

/*prototype给function添加了两个属性,一个是div,一个是text,这里似乎是利用了浏览器本身的功能来做escape
等到后面看到的时候再说吧*/
  escapeHTML: function() {
    var self = arguments.callee;
    self.text.data = this;
    return self.div.innerHTML;
  },

  unescapeHTML: function() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? (div.childNodes.length > 1 ?
      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
      div.childNodes[0].nodeValue) : '';
  },

  toQueryParams: function(separator) {
/*
把类似于param1=value1&param2=value2...&paramn=valuen#dock这样的uri拆分
返回一个对象,对象包含n个属性,属性名分别为param1,param2....paramn,对应的值分别为value1,value2...valuen
*/
    var match = this.strip().match(/([^?#]*)(#.*)?$/);
    if (!match) return {};

    return match[1].split(separator || '&').inject({}, function(hash, pair) {
      if ((pair = pair.split('='))[0]) {
        var key = decodeURIComponent(pair.shift());
        /*主要是为了防止value值本身中包含等号,例如某个param名叫expression,他的value为"x=10*10-y;"
        若不考虑这种情况可能会导致params截断出错*/
        var value = pair.length > 1 ? pair.join('=') : pair[0];
        if (value != undefined) value = decodeURIComponent(value);

        /*如果字符串中包含了多个同名的param,则这这个param对应的values会放入一个数组*/
        /*例如有一个查询字符串name=jacobo&sex=male&hobit=soccer&hobit=music
        经过toQueryParams后会返回一个对象{name:jacobo,sex:male,hobit:[soccer,music]}*/
        if (key in hash) {
          if (hash[key].constructor != Array) hash[key] = [hash[key]];
          hash[key].push(value);
        }
        else hash[key] = value;
      }
      return hash;
    });
  },

  toArray: function() {
    return this.split('');
  },

/*succ方法和ruby中的几乎一样
var str = "1"
str.succ 输出结果为"2"
var str = "abcd"
str.succ 输出结果为"abce"
*/
  succ: function() {
    return this.slice(0, this.length - 1) +
      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
  },

/*times不知道是不是也是来源于ruby,用法有差别不过效果一样
var str = "ab";
str.times(5);输出结果为"ababababab"五次"ab"
*/
  times: function(count) {
    var result = '';
    for (var i = 0; i < count; i++) result += this;
    return result;
  },


/*将类似于"ab-cd-ef-gh"这样的字符串转化为"abCdEfGh"*/
  camelize: function() {
    var parts = this.split('-'), len = parts.length;
    if (len == 1) return parts[0];

/*不明白这句话的意思,如果字符串第一个字符为'-',直接忽略掉parts[0]不就ok了么,高人写的代码就是不明白*/
    var camelized = this.charAt(0) == '-'
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
      : parts[0];

    for (var i = 1; i < len; i++)
      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

    return camelized;
  },

/*大写首字母*/
  capitalize: function() {
    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
  },

/*将大小写混杂的字符串按照大小写分割,然后再用下划线连接起来
例如
var str = "aBCd-eFg";
str.underscore;输出结果为"a_BC_d_e_F_g
*/
  underscore: function() {
    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
  },

/*将下划线替换为'-'
例如
var str = "a_b_c";
str.dasherize; 输出"a-b-c"
*/
  dasherize: function() {
    return this.gsub(/_/,'-');
  },

/*暂时不明白,留到最后看,不过ms和ruby中的inspect功能是一致的*/
  inspect: function(useDoubleQuotes) {
    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
      var character = String.specialChar[match[0]];
      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
    });
    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
  },

  toJSON: function() {
    return this.inspect(true);
  },

  unfilterJSON: function(filter) {
    return this.sub(filter || Prototype.JSONFilter, '#{1}');
  },

  isJSON: function() {
    var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
  },

  evalJSON: function(sanitize) {
    var json = this.unfilterJSON();
    try {
      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
    } catch (e) { }
    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
  },

/*确定字符串是否包含某个子字符串*/
  include: function(pattern) {
    return this.indexOf(pattern) > -1;
  },

/*是否以某个字符串开头*/
  startsWith: function(pattern) {
    return this.indexOf(pattern) === 0;
  },

/*是否以某个字符串结尾*/
  endsWith: function(pattern) {
    var d = this.length - pattern.length;
    return d >= 0 && this.lastIndexOf(pattern) === d;
  },

/*判断字符串是否为空字符串(也就是是否为"")*/
  empty: function() {
    return this == '';
  },

/*是否为仅包含空格的字符串*/
  blank: function() {
/*此处用到了javascript正则的test方法*/
    return /^\s*$/.test(this);
  }
});

/*IE里面处理escapeHTML和unescapeHTML的方式和在firefox中不同,此处重新定义了一遍
就是用正则查找然后几个关键字"&","<",">"转义
*/
if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
  escapeHTML: function() {
    return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
  },
  unescapeHTML: function() {
    return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
  }
});

String.prototype.gsub.prepareReplacement = function(replacement) {
  if (typeof replacement == 'function') return replacement;
  var template = new Template(replacement);
  return function(match) { return template.evaluate(match) };
}

/*给toQueryParams起了一个别名,叫做parseQuery*/
String.prototype.parseQuery = String.prototype.toQueryParams;

/*给String类型实例的escapeHTML方法添加了两个方法
div:创建一个层
text:创建了一个Text节点
*/
Object.extend(String.prototype.escapeHTML, {
  div:  document.createElement('div'),
  text: document.createTextNode('')
});


var Template = Class.create();
/*这个正则实在不明白。。。*/
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype = {
  initialize: function(template, pattern) {
    this.template = template.toString();
    this.pattern  = pattern || Template.Pattern;
  },

  evaluate: function(object) {
    return this.template.gsub(this.pattern, function(match) {
      var before = match[1];
/*如果replacement字符串以'\'开头,则直接返回后面的"#{some words here}"
否则,返回replacement的第一个字符+"#some words here",注意这里会去掉{} */
/*不明白道理*/
      if (before == '\\') return match[2];
      return before + String.interpret(object[match[3]]);
    });
  }
}

var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');

var Enumerable = {
/*对枚举类型进行扩展,添加each方法,each方法的参数为一个两个参数的函数
函数第一个参数接收每一轮枚举时的枚举对象,第二个参数指示该枚举值位于原枚举类型中的第几项,当然,这两个参数也是可以省略的
若函数执行中抛出异常,则枚举过程立刻停止
usage:
  var arr = new Array;
  arr.each(function(value,index){...});
实际的例子:
  var arr = [0,1,2,3,4,5];
  arr.each(function(value,index){ alert("value is "+String(value)+",index is "+String(index)+".");});
*/
/*iterator的返回值被忽略*/
  each: function(iterator) {
    var index = 0;
    try {
/*_each可枚举类型自带的一个方法,可枚举类型包括Array*/
      this._each(function(value) {
        iterator(value, index++);
      });
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  },

/*
	var arr = [1,2,3,4,5];
	alert(arr.eachSlice(2).inspect());
        输出结果为[[1,2],[3,4],[5]]
*/
  eachSlice: function(number, iterator) {
    var index = -number, slices = [], array = this.toArray();
    while ((index += number) < array.length)
      slices.push(array.slice(index, index+number));
    return slices.map(iterator);
  },

/*对可枚举类型中的每一个元素调用传入的iterator方法进行处理,最后返回true或者false,如果不传入iterator方法,则比较可枚举类型中的每一个枚举项,
若枚举项中有NaN,undefined,null,则停止枚举,结果返回false*/
/*iterator的返回值被忽略*/
  all: function(iterator) {
    var result = true;
    this.each(function(value, index) {
/*注意这里的用法,js的弱类型特性一目了然*/
      result = result && !!(iterator || Prototype.K)(value, index);
      if (!result) throw $break;
    });
    return result;
  },

/*任意一项执行成功则枚举停止*/
/*iterator的返回值被忽略*/
  any: function(iterator) {
    var result = false;
    this.each(function(value, index) {
      if (result = !!(iterator || Prototype.K)(value, index))
        throw $break;
    });
    return result;
  },

/*对枚举中所有元素进行处理,并将处理结果保存并且返回
此时需要iterator将单个元素的处理结果返回*/
/*
	var arr = [1,2,3,4,5];
	arr.collect(function(value){ return value.succ(); } ).each(function(value) { alert(value); })
	弹出窗口分别显示2,3,4,5,6
*/
  collect: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      results.push((iterator || Prototype.K)(value, index));
    });
    return results;
  },

/*对枚举类型中所有元素依次处理,若iterator函数返回true,则终止枚举,并返回当前枚举项的值*/
/*
	var arr = [1,2,3,4,5];
	alert(arr.detect(function(value){return value>3; }));
	弹出窗口显示4
*/
  detect: function(iterator) {
    var result;
    this.each(function(value, index) {
      if (iterator(value, index)) {
        result = value;
        throw $break;
      }
    });
    return result;
  },

/*对枚举类型中所有元素一次处理,若iterator函数返回非NaN,null,undefined,false
则将当前枚举元素的值存放到一个新的枚举类型中,最后返回此新的枚举类新*/
  findAll: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (iterator(value, index))
        results.push(value);
    });
    return results;
  },

/*加强版的findAll,先用正则匹配出符合pattern的元素,然后使用iterator进行处理,最后将处理后的结果存放在数组中返回*/
  grep: function(pattern, iterator) {
    var results = [];
    this.each(function(value, index) {
      var stringValue = value.toString();
      if (stringValue.match(pattern))
        results.push((iterator || Prototype.K)(value, index));
    })
    return results;
  },

/*判断数组中是否包含某个元素*/
/*包含则返回true,否则返回false*/
/*注意这里用==来进行比较,也就是说如果经过转换相等的,也会返回true
	var arr = [1,2,3,4,5];
	alert(arr.include("3"));
*/
  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  },

/*把数组分为指定大小的子数组,如果不够的话,用指定的fillwith进行填充*/
/* var arr = [1,2,3];
   arr.inGroupsOf(2,0);
返回结果为[[1,2],[3,0]]
*/
  inGroupsOf: function(number, fillWith) {
    fillWith = fillWith === undefined ? null : fillWith;
    return this.eachSlice(number, function(slice) {
      while(slice.length < number) slice.push(fillWith);
      return slice;
    });
  },

/*inject,用法和ruby里面的inject一模一样*/
/*此处的interator需要三个参数function(memo,value,index){...}*/
/*
	var arr = [1,2,3,4,5];
	alert(arr.inject(0,function(memo,value){ return memo+value; } ));
*/
  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  },

/*
对数组中所有元素调用指定的方法,参数为方法名和参数列表
	var arr = [1,2,3,4,5];
	alert(arr.invoke("succ").inspect());
*/
  invoke: function(method) {
    var args = $A(arguments).slice(1);
    return this.map(function(value) {
      return value[method].apply(value, args);
    });
  },

/*找到最大的元素,如果iterator为一个函数,则比较经过此函数处理后的每一个元素,若不定义iterator,
则直接找到最大的元素并返回*/
/*这里有个问题,如果数组中包含一个NaN,或者undefined,或者null,或者iterator的返回值不小心为NaN/undefined/null了,那么最大值岂不是成NaN/undefined/null了?*/
  max: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value >= result)
        result = value;
    });
    return result;
  },

  min: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value < result)
        result = value;
    });
    return result;
  },

/*对数组项进行分组,经过iterator处理后返回true的分为一组,false的分为一组*/
/*结果为一个包含数组的数组*/
  partition: function(iterator) {
    var trues = [], falses = [];
    this.each(function(value, index) {
      ((iterator || Prototype.K)(value, index) ?
        trues : falses).push(value);
    });
    return [trues, falses];
  },

/*取出每一个元素的property属性的值,返回一个包含这些值的数组*/
/*Luciano学英语:
pluck: [ pl?k ]   

n. 勇气,猛拉,动物内脏
v. 摘,猛拉,拔

词形变化:
名词:plucker 动词过去式:plucked 过去分词:plucked 现在分词:plucking 第三人称单数:plucks 
*/
  pluck: function(property) {
    var results = [];
    this.each(function(value, index) {
      results.push(value[property]);
    });
    return results;
  },

/*和ruby里面用法一样,结果iterator处理,返回false的元素将不会包含在返回的数组中*/
/* var arr = [1,2,3,4,5];
   arr.reject(function(value){ return(value>2 && value<5) }).each(function(value){alert(value);});
*/
  reject: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator(value, index))
        results.push(value);
    });
    return results;
  },

/*sortBy传入一个函数,此参数不能省略,用来处理数组中的每一个元素,并且将处理结果保存起来,用来作为排序的依据(升序排列)*/
/*luciano学英语*/
/*
criteria: [ krai'ti?ri? ]   

n. 标准

例句与用法:
1.	What are the criteria for deciding (ie How do we decide) who gets the prize? 
	评定获奖者以什麽作标准?
2.	An experiment was made to check up on the reliability of certain criteria. 
	已经进行了一项实验以检查某些标准的可靠性。
3.	Success in making money is not always a good criterion of success in life. 
	能挣钱并不一定是衡量人生幸福的可靠标准.
*/
  sortBy: function(iterator) {
    return this.map(function(value, index) {
      return {value: value, criteria: iterator(value, index)};
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }).pluck('value');
  },

/*toArray = map = collect()*/
  toArray: function() {
    return this.map();
  },

  zip: function() {
    var iterator = Prototype.K, args = $A(arguments);
    if (typeof args.last() == 'function')
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      return iterator(collections.pluck(index));
    });
  },

  size: function() {
    return this.toArray().length;
  },

  inspect: function() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }
}

Object.extend(Enumerable, {
  map:     Enumerable.collect,
  find:    Enumerable.detect,
  select:  Enumerable.findAll,
  member:  Enumerable.include,
  entries: Enumerable.toArray
});

/* $A方法将返回一个数组*/
/*如果对象有toArray()方法的话会直接调用对象的toArray方法*/
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

/*因为js是脚本语言,所以后设置的会覆盖先前设置的*/
if (Prototype.Browser.WebKit) {
  $A = Array.from = function(iterable) {
    if (!iterable) return [];
    if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
      iterable.toArray) {
      return iterable.toArray();
    } else {
      var results = [];
      for (var i = 0, length = iterable.length; i < length; i++)
        results.push(iterable[i]);
      return results;
    }
  }
}

Object.extend(Array.prototype, Enumerable);

/*reverse是js Array对象的内部方法*/
if (!Array.prototype._reverse)
  Array.prototype._reverse = Array.prototype.reverse;

/*nnd原来_each方法也是扩展上去的*/
Object.extend(Array.prototype, {
  _each: function(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  },

/*敢情这样就能清空数组元素,长见识了*/
  clear: function() {
    this.length = 0;
    return this;
  },

  first: function() {
    return this[0];
  },

  last: function() {
    return this[this.length - 1];
  },

/*压缩数组,剔除其中所有值为null的元素*/
  compact: function() {
    return this.select(function(value) {
      return value != null;
    });
  },

/*同ruby中的flatten用法一致*/
/*
	var arr=[[1,2],3,[5,6]];
	alert(arr.flatten().inspect());
输出结果[1,2,3,5,6]
*/
  flatten: function() {
    return this.inject([], function(array, value) {
      return array.concat(value && value.constructor == Array ?
        value.flatten() : [value]);
    });
  },

/*得到一个不包含参数中指定元素的新数组*/
/*
	var arr=[1,2,3,4,5,6];
	alert(arr.without(2,3,6).inspect();
输出结果为[1,4,5]
*/
  without: function() {
    var values = $A(arguments);
    return this.select(function(value) {
      return !values.include(value);
    });
  },

/*得到指定元素在数组中的索引*/
  indexOf: function(object) {
    for (var i = 0, length = this.length; i < length; i++)
      if (this[i] == object) return i;
    return -1;
  },

  reverse: function(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  },

  reduce: function() {
    return this.length > 1 ? this : this[0];
  },

  uniq: function(sorted) {
    return this.inject([], function(array, value, index) {
      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
        array.push(value);
      return array;
    });
  },

/*这个太巧妙了,经典*/
  clone: function() {
    return [].concat(this);
  },

  size: function() {
    return this.length;
  },

  inspect: function() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  },

  toJSON: function() {
    var results = [];
    this.each(function(object) {
      var value = Object.toJSON(object);
      if (value !== undefined) results.push(value);
    });
    return '[' + results.join(', ') + ']';
  }
});

Array.prototype.toArray = Array.prototype.clone;

/*就是ruby中的%w方法*/
/* alert($w(1 2 3 4 5));
输出结果为[1,2,3,4,5]
*/
function $w(string) {
  string = string.strip();
  return string ? string.split(/\s+/) : [];
}

if (Prototype.Browser.Opera){
  Array.prototype.concat = function() {
    var array = [];
    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
    for (var i = 0, length = arguments.length; i < length; i++) {
      if (arguments[i].constructor == Array) {
        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
      } else {
        array.push(arguments[i]);
      }
    }
    return array;
  }
}

/*哈希类型的构造函数*/
var Hash = function(object) {
  if (object instanceof Hash) this.merge(object);
  else Object.extend(this, object || {});
};

/*扩展了Hash类型,添加了toQueryString()和toJSON方法*/
/*usage:
	var hash = new Hash({name:'jacobo',age:17});
	alert(hash.toQueryString());
	输出结果name=jacobo&age=17
*/
Object.extend(Hash, {
  toQueryString: function(obj) {
    var parts = [];
    parts.add = arguments.callee.addPair;

    this.prototype._each.call(obj, function(pair) {
      if (!pair.key) return;
      var value = pair.value;

      if (value && typeof value == 'object') {
        if (value.constructor == Array) value.each(function(value) {
          parts.add(pair.key, value);
        });
        return;
      }
      parts.add(pair.key, value);
    });

    return parts.join('&');
  },
  
/*usage:
	var hash = new Hash({name:'jacobo',age:17});
	alert(hash.toJSON());
	输出结果{"name":"jacobo","age":"17"}
*/
  toJSON: function(object) {
    var results = [];
    this.prototype._each.call(object, function(pair) {
      var value = Object.toJSON(pair.value);
      if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
    });
    return '{' + results.join(', ') + '}';
  }
});

Hash.toQueryString.addPair = function(key, value, prefix) {
  key = encodeURIComponent(key);
  if (value === undefined) this.push(key);
  else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
}

/*把Enumerable中的方法mixin到Hash.prototype中去*/
Object.extend(Hash.prototype, Enumerable);
Object.extend(Hash.prototype, {
/*给Hash.prototype添加_each方法,在Enumerable中,实际上each方法方法内部调用的就是_each方法*/
  _each: function(iterator) {
    for (var key in this) {
      var value = this[key];
      if (value && value == Hash.prototype[key]) continue;

      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },

  keys: function() {
    return this.pluck('key');
  },

  values: function() {
    return this.pluck('value');
  },

/*利用Enumerable的inject方法对两个哈希进行合并
  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  }
*/
  merge: function(hash) {
    return $H(hash).inject(this, function(mergedHash, pair) {
      mergedHash[pair.key] = pair.value;
      return mergedHash;
    });
  },

/*可以传入多个参数,会从object中删除相应的属性
如果传入一个参数,会返回此参数对应属性的值,
如果传入多个参数,会返回包含这些参数对应属性值的数组*/
/*
	var hash = new Hash({name:'jacobo',age:17,sex:"male",hobit:['football','rock']});
    alert(hash.remove("age","hobit").inspect()); 
    弹出提示[17,['football','rock']]
*/
  remove: function() {
    var result;
    for(var i = 0, length = arguments.length; i < length; i++) {
      var value = this[arguments[i]];
      if (value !== undefined){
        if (result === undefined) result = value;
        else {
          if (result.constructor != Array) result = [result];
          result.push(value)
        }
      }
      delete this[arguments[i]];
    }
    return result;
  },

  toQueryString: function() {
    return Hash.toQueryString(this);
  },

  inspect: function() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  },

  toJSON: function() {
    return Hash.toJSON(this);
  }
});

function $H(object) {
  if (object instanceof Hash) return object;
  return new Hash(object);
};

// Safari iterates over shadowed properties
/*为了消除浏览器的差异,针对于Safari浏览器重新定义了_each方法,主要差别是Safari中的对象可能存在同名的key*/
/*这段代码就是为了进行测试
function() {
  var i = 0, Test = function(value) { this.key = value };
  Test.prototype.key = 'foo';
  for (var property in new Test('bar')) i++;
  return i > 1;
}()
*/
if (function() {
  var i = 0, Test = function(value) { this.key = value };
  Test.prototype.key = 'foo';
  for (var property in new Test('bar')) i++;
  return i > 1;
}()) Hash.prototype._each = function(iterator) {
  var cache = [];
  for (var key in this) {
    var value = this[key];
    if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
    cache.push(key);
    var pair = [key, value];
    pair.key = key;
    pair.value = value;
    iterator(pair);
  }
};

/*ObjectRange对象,看起来非常类似ruby中的Range*/
/*ObjectRange操作的对象必须实现了succ()方法*/
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
/*exclusive指示是否包含下边界(总是包含上边界)*/
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

  _each: function(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  },

  include: function(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }
});

/*ObjectRange的快捷命名*/
var $R = function(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}
 

 

分享到:
评论
2 楼 lnj888 2010-05-26  
收藏起来了 谢谢哈!
video converter
1 楼 genius 2008-08-10  
好东西啊,谢谢你了!

相关推荐

    Really easy field validation with Prototype 1.5.4.1 中文修改版

    所做的更改: &lt;br&gt;1、prototype.js 版本更新为 v1.5.1.1 &lt;br&gt;2、effects.js 版本更新为 v1.7.1_beta3 &lt;br&gt;3、所有校验错误提示信息均修改为中文,提供UTF-8和GB18030两种编码的版本 &lt;br&gt;4、增加"YYYY-MM...

    prototype.js

    其中里面包含了prototype1.5 prototype1.5.1 prototype1.5.1.1 prototype1.5.1.2 prototype1.6.0。五个版本。 http://blog.csdn.net/boat1980/archive/2008/04/10/2278259.aspx这个连接有1.5.1.1代码的注释。

    Prototype.js

    Prototype.js (ver:1.5.1.1) Prototype.js 帮助(ver:1.5.1)英文PDF Prototype.js 帮助(ver:1.4)中文CHM Prototype.js 帮助(ver:1.4)中文PDF

    Prototype 1.5 中文手册.rar

    - `Prototype.extend`:此方法允许向对象添加新的属性或方法,实现对象的扩展。 - `Event`模块:提供事件处理相关的函数,如`observe`、`stopObserving`等,便于事件监听和移除。 3. Ajax功能: Prototype库的...

    Prototype 1.5 中文文档 chm

    Prototype 最新的1.5 版中文文档,chm格式,很多人都在找。Prototype 是一个非常优秀的javascript基础类库,可以很好的支持Ajax,国外有多个基于此类库的扩展,这是最新的1.5中文文档,AJAX编程必备手册。

    prototype中文手册及API

    prototype中文手册及API --------------------- prototype.js(1.5.1.1) prototype中文手册 prototype.chm

    prototype-1.6.0.3.js+prototype1.4 、1.5中文手册+prototype1.6英文手册

    Prototype通过`Ajax`类封装了这一技术,包括`Ajax.Request`、`Ajax.Updater`和`Ajax.PeriodicalUpdater`等方法,使得创建异步请求变得简单直观。 总结来说,这个压缩包是学习和使用Prototype JavaScript库的宝贵...

    prototype_1.7.3.js 最新版本

    《prototype_1.7.3.js:JavaScript框架的里程碑》 在JavaScript的世界里,Prototype库是一个不可...无论你是新手还是经验丰富的开发者,掌握Prototype.js都能让你在Web开发中如虎添翼,进一步提升代码质量和开发效率。

    prototype.js 源码解读, 中文帮助文档

    开发者网站: http://prototype.conio.net/ prototype学习资料包括: prototype14参考 prototype 1.3 源码解读.txt prototype 1.5 参考图 prototype 1.5pre1.js prototype 1.4.js

    prototype1.5中文说明

    通过阅读`Prototype.doc`文档,你可以深入了解Prototype库的每个细节,学习如何有效地利用这些功能来构建高效、动态的Web应用程序。无论你是JavaScript新手还是经验丰富的开发者,Prototype 1.5RC2都是一个值得学习...

    prototype 1.6.0.2.js+使用DEMO例子

    通过提供的DEMO例子,开发者可以直观地看到Prototype在实际项目中的应用,理解如何将这些工具和方法融入到自己的代码中。实践中,可能包括创建动态页面、实现异步数据交互、优化DOM操作等方面。 总的来说,这个...

    基于ASP的风铃ASP文件共享系统(多文件上传) v1.5.zip

    总的来说,"基于ASP的风铃ASP文件共享系统(多文件上传) v1.5.zip"是一个实用的文件管理工具,它展示了ASP在开发动态网站方面的应用。了解其工作原理和特点,对于学习和提升ASP编程技能,以及理解文件共享系统的实现...

    prototype 1.6中文手册 chm+prototype 1.6.js源码 最新版

    包含的"prototype.js"文件是Prototype 1.6.0的源代码,这对于开发者来说是一份宝贵的参考资料。通过阅读源码,开发者可以直接了解每个函数的实现细节,理解其工作原理,从而更好地应用到自己的项目中。源码中的注释...

    prototype1.6.0.2.js

    prototype1.6.0.2

    prototype.js 1.6中文手册、prototype.js 1.6英文手册、

    Prototype.js 是一个开源的JavaScript库,它扩展了JavaScript语言,为开发者提供了许多便利的功能,特别是在对象操作、DOM操作和事件处理方面。1.6版本是该库的一个重要里程碑,引入了诸多改进和新特性。 ### 1. ...

    prototype1.5

    Prototype 1.5,作为JavaScript库的一个重要里程碑,为Web开发引入了强大的功能和灵活性,尤其在处理Ajax(异步JavaScript和XML)交互方面。这个版本的发布极大地简化了前端开发,使得开发者能够更加高效地构建动态...

    prototype1.6.1 .js

    prototype1.6.1 .js 时下流行的前端开发javascript类库

    Prototype.and.script.aculo.us.Dec.2007.pdf

    《Prototype与script.aculo.us:深入理解与应用》一书为读者提供了全面而深入的JavaScript框架知识,尤其针对Prototype和script.aculo.us两大框架。本书不仅涵盖了基础概念,还深入探讨了高级编程技巧,旨在帮助...

    prototype1.7.zip

    例如,`Object.extend()`方法允许我们轻松地合并两个或多个对象,而`Function.prototype.bind()`则使我们能够固定函数的上下文,确保`this`关键字始终指向预期的对象。 2. **DOM操作** Prototype 提供了一套强大...

    prototype1.6.0.3.rar

    Prototype JavaScript框架,作为一个历史悠久且广泛使用的库,为开发者提供了许多便利的功能,使得DOM操作、事件处理以及Ajax通信变得更加简单。本文将围绕Prototype 1.6.0.3这一版本,深入探讨其核心概念、主要功能...

Global site tag (gtag.js) - Google Analytics