若是你想研究一些比較大型的js
框架的源碼的話,本人建議你從其最初的版本開始研讀,由於最初的版本東西少,易於研究,然後的版本基本都是在其基礎上不斷擴充罷了,因此,接下來我不許備徹底解讀prototype.js
的源碼了,而是拿它一些常見的API
來解讀。javascript
//定時器類,比起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; } } } }
給變量賦值的狀況:java
賦`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字符串進行編碼,例如將<轉換爲< 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(