如果你想研究一些比较大型的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;
}
}
}
}

给变量赋值的情况:

赋`undefined`值:表明对象属性或方法不存在,或声明了变量但从未赋值。

赋`null`值:包含 `null` 的变量包含“无值”或“无对象”。换句话说,该变量没有保存有效的数、字符串、`boolean`、数组或对象。可以通过给一个变量赋 `null` 值来清除变量的内容。也表明这个变量是用来存放对象的。

//为字符串对象添加方法,和前面为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字符串进行编码,例如将<转换为&lt;
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() {
return this.gsub(/_/,'-');
}, //将字符串转换为可观察的形式。这里将转义字符写成转义前的字符串形式
inspect: function(useDoubleQuotes) {
var escapedString = this.replace(/\\/g, '\\\\');
if (useDoubleQuotes)
return '"' + escapedString.replace(/"/g, '\\"') + '"';
else
return "'" + escapedString.replace(/'/g, '\\\'') + "'";
}
});

注:i:忽略大小写,g全局匹配,m多行匹配

String对象中的正则表达式法:

方法 含义
match(pattern) 返回pattern中的子串或null
replace(pattern,replacement) 用replacement替换pattern
search(pattern) 返回字符串中pattern开始位置
split(pattern) 返回字符串按指定pattern拆分的数组

all: function(iterator) {
var result = true;
this.each(function(value, index) {
result = result && !!(iterator || Prototype.K)(value, index);
if (!result) throw $break;
});
return result;
}, /*判断枚举对象中的所有元素是否有满足指定迭代器的值(返回true),如果有则返回true,否则返回false
*/
其原理和all方法类似
any: function(iterator) {
var result = false;
this.each(function(value, index) {
if (result = !!(iterator || Prototype.K)(value, index))
throw $break;
});
return result;
},
/*
返回所有枚举元素通过迭代器执行的结果,作为数组返回
*/
collect: function(iterator) {
var results = [];
this.each(function(value, index) {
results.push((iterator || Prototype.K)(value, index));
});
return results;
}, /*返回第一个能够使得迭代器返回true的枚举元素的值,如果没有true,则返回"undefined",即result未被赋值
*/
detect: function(iterator) {
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
result = value;
throw $break;
}
});
return result;
},
/*
返回所有能够使得迭代器返回true的枚举元素,作为数组返回。
*/
findAll: function(iterator) {
var results = [];
this.each(function(value, index) {
if (iterator(value, index))
results.push(value);
});
return results;
}, 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;
}, include: function(object) {
var found = false;
this.each(function(value) {
if (value == object) {
found = true;
throw $break;
}
});
return found;
},
/**
* Element 就象一个 java 的工具类,主要用来 隐藏/显示/销除 对象,以及获取对象的简单属性。
*
*/
if (!window.Element) {
var Element = new Object();
} Object.extend(Element, {
/**
* 切换 显示/隐藏
*/
toggle: function() {
for (var i = 0; i < arguments.length; i++) {
var element = $(arguments[i]);
element.style.display =
(element.style.display == 'none' ? '' : 'none');//三目运算符判断
}
}, hide: function() {
for (var i = 0; i < arguments.length; i++) {
var element = $(arguments[i]);//将选中的参数赋值给element
element.style.display = 'none';//你懂的
}
}, show: function() {
for (var i = 0; i < arguments.length; i++) {
var element = $(arguments[i]);
element.style.display = '';
}
}, /**
* 从父节点中移除
*/
remove: function(element) {
element = $(element);
element.parentNode.removeChild(element);
}, getHeight: function(element) {
element = $(element);
return element.offsetHeight;
}, /**
* 是否拥有 class 属性值
*/
hasClassName: function(element, className) {
element = $(element);
if (!element)
return;
var a = element.className.split(' ');
for (var i = 0; i < a.length; i++) {
if (a[i] == className)
return true;
}
return false;
}, /**
* 为对象添加 class 属性值
*/
addClassName: function(element, className) {
element = $(element);
Element.removeClassName(element, className);
element.className += ' ' + className;
}, /**
* 为对象移除 class 属性值
*/
removeClassName: function(element, className) {
element = $(element);
if (!element)
return;
var newClassName = '';
var a = element.className.split(' ');
for (var i = 0; i < a.length; i++) {
if (a[i] != className) {
if (i > 0)
newClassName += ' ';
newClassName += a[i];
}
}
element.className = newClassName;
}, // removes whitespace-only text node children
cleanWhitespace: function(element) {
var element = $(element);
for (var i = 0; i < element.childNodes.length; i++) {
var node = element.childNodes[i];
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
Element.remove(node);
}
}
});
 

prototype.js 源码解读(02)的更多相关文章

  1. prototype.js 源码解读(01)

    prototype.js是一个设计的非常优雅且很有实用价值的js基础类库,其源码非常值得研究.研究它的源码不仅能提升个人水平,而且对你打下坚实的js基础也很有帮助.因本人技术水平有限,该解读仅供参考. ...

  2. js便签笔记(10) - 分享:json2.js源码解读笔记

    1. 如何理解“json” 首先应该意识到,json是一种数据转换格式,既然是个“格式”,就是个抽象的东西.它不是js对象,也不是字符串,它只是一种格式,一种规定而已. 这个格式规定了如何将js对象转 ...

  3. js便签笔记(10) - 分享:json.js源码解读笔记

    1. 如何理解“json” 首先应该意识到,json是一种数据转换格式,既然是个“格式”,就是个抽象的东西.它不是js对象,也不是字符串,它只是一种格式,一种规定而已. 这个格式规定了如何将js对象转 ...

  4. fastclick.js源码解读分析

    阅读优秀的js插件和库源码,可以加深我们对web开发的理解和提高js能力,本人能力有限,只能粗略读懂一些小型插件,这里带来对fastclick源码的解读,望各位大神不吝指教~! fastclick诞生 ...

  5. json2.js源码解读记录

    相关内容:json详细用法.js语法.unicode.正则   json特点--最简单.最小巧的经典js库.   json作者:道克拉斯.克劳福德(Douglas Crockford)--js大牛 出 ...

  6. require.js 源码解读——配置默认上下文

    首先,我们先来简单说一下,require.js的原理: 1.载入模块
 2.通过模块名解析出模块信息,以及计算出URL
 3.通过创建SCRIPT的形式把模块加载到页面中.
 4.判断被加载的脚本,如 ...

  7. 亚马逊左侧菜单延迟z三角 jquery插件jquery.menu-aim.js源码解读

    关于亚马逊的左侧菜单延迟,之前一直不知道它的实现原理.梦神提到了z三角,我也不知道这是什么东西.13号那天很有空,等领导们签字完我就可以走了.下午的时候,找到了一篇博客:http://jayuh.co ...

  8. 前端编译原理 parser.js源码解读

    前面已经介绍了一个jison的使用,在正常开发中其实已经够用下,下面主要是看了下parser.js代码解读下,作为一些了解. 下面以最简单的文法产生的parser做一些代码注释 下面是一些注释,标示了 ...

  9. prototype.js源码

    prototype 1.3.1 版本和之前的 1.2.0 版本有了不少改进,并增加了新的功能: 1. 增加了事件注册管理2. 增加了空间定位的常用函数3. 改善了 xmlhttp 的封装4. 移除了 ...

随机推荐

  1. 基于单个 div 的 CSS 画图

    原文: Single Div Drawings with CSS 译文: 基于单个 div 的 CSS 画图 译者: 前端外刊评论 译注:通读本文,强烈地感受到了技术与艺术的结合.赞作者的这句话:Re ...

  2. Android实战技巧之六:PreferenceActivity使用详解

    一.写作前面 当我们做应用的时候,需要用户配置一些信息,而这就是通常所说的应用设置. 对于Android系统来说,系统本身的设置带来的用户体验和习惯已经深入人心,在我们的应用中同样用到类似的设置页, ...

  3. Java获取真实的IP地址--转载

    // 获取真实IP的方法() public String getIpAddr() { String ip = request.getHeader("x-forwarded-for" ...

  4. 【转】JavaScript中的constructor与prototype

    最初对js中 object.constructor 的认识: 在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下 ...

  5. ionic 项目分享No.2——简化版【转】

    写在文章前:由于最近研究ionic框架,深感这块的Demo寥寥可数,而大家又都藏私,堂堂天朝,何时才有百家争鸣之象,开源精神吾辈当仁不让!                                ...

  6. CI框架篇之模型篇--初识(1)

    模型 模型是专门用来和数据库打交道的PHP类.例如,假设你想用CodeIgniter来做一个Blog. 你可以写一个模型类,里面包含插入.更新.删除Blog数据的方法. 下面的例子将向你展示一个普通的 ...

  7. Handler 原理分析和使用(一)

    我为什么写Handler,原因主要还在于它在整个 Android 应用层面非常之关键,他是线程间相互通信的主要手段.最为常用的是其他线程通过Handler向主线程发送消息,更新主线程UI. 下面是一个 ...

  8. js基础知识之_函数

    javascript函数 函数概念 将完成某一特定功能的代码集合起来,可以重复使用 白话函数理解-函数就是一个工厂,帮大家实现某一个功能 优点 -时程序更加简洁 -逻辑更有条例 -调用方便 -维护更加 ...

  9. javascript-图片横向无缝隙滚动(可在服务器运行)

    前两次弄'图片横向滚动'javascript,在本地上运行得很美,可是一上到我们学校后台的服务器,就有很多问题,这个算是行的了. css代码: <style type="text/cs ...

  10. java中的递归方法

    一.含义 递归算法是一种直接或间接地调用自身的算法.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 二.例子 99乘法表的例子 1:普通实现99乘法表太 ...