筆記內容多摘錄自《JavaScript設計模式與開發實踐》(曾探著),侵刪。javascript
同一操做做用於不一樣的對象上,能夠產生不一樣的解釋和不一樣的執行結果。java
多態背後的思想是將「作什麼」和「誰去作」以及「怎麼作」分離開來,也就是將「不變的事物」與「可能改變的事物分離開」編程
封裝的目的是將信息隱藏設計模式
Object.create = Object.create || function( obj ){ var F = function(){}; F.prototype = obj; return new F(); }
this的指向閉包
用途app
把請求封裝爲對象,分離請求發起者和接收者(執行者)之間的耦合關係函數
var Tv = { open: function () { console.log('打開電視機'); }, close: function () { console.log('關上電視機'); } }; var createCommand = function (receiver) { var execute = function () { return receiver.open(); // 執行命令,打開電視機 } var undo = function () { return receiver.close(); // 執行命令,關閉電視機 } return { execute: execute, undo: undo } }; var setCommand = function (command) { document.getElementById('execute').onclick = function () { command.execute(); // 輸出:打開電視機 } document.getElementById('undo').onclick = function () { command.undo(); // 輸出:關閉電視機 } }; setCommand(createCommand(Tv));
命令的接收着封閉在閉包中this
函數柯里化、部分求值prototype
var currying = function (fn) { var args = []; return function () { if (arguments.length === 0) { return fn.apply(this, args); } else { [].push.apply(args, arguments); return arguments.callee; } } }; var cost = (function () { var money = 0; return function () { for (var i = 0, l = arguments.length; i < l; i++) { money += arguments[i]; } return money; } })(); var cost = currying(cost); // 轉化成currying 函數 cost(100); // 未真正求值 cost(200); // 未真正求值 cost(300); // 未真正求值 alert(cost()); // 求值並輸出:600
泛化this的提取過程設計
Function.prototype.uncurrying = function () { var self = this; return function () { var obj = Array.prototype.shift.call(arguments); return self.apply(obj, arguments); }; };
Function.prototype.uncurrying = function () { var self = this; return function () { return Function.prototype.call.apply(self, arguments); } };
var throttle = function (fn, interval) { var __self = fn, // 保存須要被延遲執行的函數引用 timer, // 定時器 firstTime = true; // 是不是第一次調用 return function () { var args = arguments, __me = this; if (firstTime) { // 若是是第一次調用,不需延遲執行 __self.apply(__me, args); return firstTime = false; } if (timer) { // 若是定時器還在,說明前一次延遲執行尚未完成 return false; timer = setTimeout(function () { // 延遲一段時間執行 clearTimeout(timer); timer = null; __self.apply(__me, args); }, interval || 500); }; } };
var timeChunk = function (ary, fn, count) { var obj, t; var len = ary.length; var start = function () { for (var i = 0; i < Math.min(count || 1, ary.length); i++) { var obj = ary.shift(); fn(obj); } }; return function () { t = setInterval(function () { if (ary.length === 0) { // 若是所有節點都已經被建立好 return clearInterval(t); } start(); }, 200); // 分批執行的時間間隔,也能夠用參數的形式傳入 }; }; var ary = []; for (var i = 1; i <= 1000; i++) { ary.push(i); }; var renderFriendList = timeChunk(ary, function (n) { var div = document.createElement('div'); div.innerHTML = n; document.body.appendChild(div); }, 8); renderFriendList();
var addEvent = function (elem, type, handler) { if (window.addEventListener) { addEvent = function (elem, type, handler) { elem.addEventListener(type, handler, false); } } else if (window.attachEvent) { addEvent = function (elem, type, handler) { elem.attachEvent('on' + type, handler); } } addEvent(elem, type, handler); }; var div = document.getElementById('div1'); addEvent(div, 'click', function () { alert(1); }); addEvent(div, 'click', function () { alert(2); });
var debounce = function (method, delay) { var timer = null; return function () { var _this = this; var args = arguments; clearTimeout(timer); timer = setTimeout(function () { method.apply(_this, args); }, delay); }; };