prototype.js 源码解读(02)
浏览数:29 /
时间:2015年06月09日
如果你想研究一些比较大型的js
框架的源码的话,本人建议你从其最初的版本开始研读,因为最初的版本东西少,易于研究,而后的版本基本都是在其基础上不断扩充罢了,所以,接下来我不准备完全解读prototype.js
的源码了,而是拿它一些常见的API
来解读。
//定时器类,比起window.setInterval函数,该类能够使得回调函数不会被并发调用
var PeriodicalExecuter = Class.create();//Class类创建的定时器类
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;//赋一个空指针,让人易于理解这是用来准备存放对象的
},
/*
相当于回调函数的一个代理。
在传统的setInterval函数中,时间一到,便强制执行回调函数,而这里加入了currentlyExecuting属性判断,
则如果callback函数的执行时间超过了一个时间片,则阻止其被重复执行。
*/
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.callback(this);
} finally {
this.currentlyExecuting = false;
}
}
}
}
给变量赋值的情况:
//为字符串对象添加方法,和前面为Number添加方法的原理相同
Object.extend(String.prototype, {
gsub: function(pattern, replacement) {
var result = ‘‘, source = this, match;
replacement = arguments.callee.prepareReplacement(replacement);
while (source.length > 0) {
if (match = source.match(pattern)) {
result += source.slice(0, match.index);
result += String.interpret(replacement(match));
source = source.slice(match.index + match[0].length);
} else {
result += source, source = ‘‘;
}
}
return result;
},
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);
});
},
scan: function(pattern, iterator) {
this.gsub(pattern, iterator);
return this;
},
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+$/, ‘‘);
},
stripTags: function() {
return this.replace(/<\/?[^>]+>/gi, ‘‘);
},
stripScripts: function() {
return this.replace(new RegExp(Prototype.ScriptFragment, ‘img‘), ‘‘);
},
//提取字符串中的脚本,返回所有脚本内容组成的数组
extractScripts: function() {
//找到所有包括<script>的代码标记
var matchAll = new RegExp(Prototype.ScriptFragment, ‘img‘);
//再对每个脚本删除<script>标记
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) });
},
//利用浏览器本身的机制对Html字符串进行编码,例如将<转换为<
escapeHTML: function() {
var div = document.createElement(‘div‘);
var text = document.createTextNode(this);
div.appendChild(text);
return div.innerHTML;
},
//对Html进行解码
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) : ‘‘;
},
/*
*获取查询字符串数组,例如通过document.location.toQueryParams()就可以得到由键和值组成的哈希表(用对象表示)。
*/
toQueryParams: function(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return {};
return match[1].split(separator || ‘&‘).inject({}, function(hash, pair) {
if ((pair = pair.split(‘=‘))[0]) {
var name = decodeURIComponent(pair[0]);
var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
if (hash[name] !== undefined) {
if (hash[name].constructor != Array)
hash[name] = [hash[name]];
if (value) hash[name].push(value);
}
else hash[name] = value;
}
return hash;
});
},
//将字符串转换为字符数组
toArray: function() {
return this.split(‘‘);
},
succ: function() {
return this.slice(0, this.length - 1) +
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
},
//将用"-"连接的字符串驼峰化
//例如:background-color转为backgroundColor
camelize: function() {
var parts = this.split(‘-‘), len = parts.length;
if (len == 1) return parts[0];
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();
},
//转换成下划线形式
underscore: function() {
return this.gsub(/::/, ‘/‘).gsub(/([A-Z]+)([A-Z][a-z])/,‘#{1}_#{2}‘).gsub(/([a-z\d])([A-Z])/,‘#{1}_#{2}‘).gsub(/-/,‘_‘).toLowerCase();
},
//转化成中划线
dasherize: function() {