function isArray(value){ return Object.prototype.toString.call(value) == "[object Array]"; } function isFunction(value){ return Object.prototype.toString.call(value) == "[object Function]"; } function isRegExp(value){ return Object.prototype.toString.call(value) == "[object RegExp]"; }
function Person(name, age, job){ if (this instanceof Person){ this.name = name; this.age = age; this.job = job; } else { return new Person(name, age, job); } } //本來,像這種沒有使用new就直接調用person的,this會被解析成window 對象 var person1 = Person("Nicholas", 29, "Software Engineer"); alert(window.name); //"" alert(person1.name); //"Nicholas" var person2 = new Person("Shelby", 34, "Ergonomist"); alert(person2.name); //"Shelby"
function Polygon(sides){ if (this instanceof Polygon) { this.sides = sides; this.getArea = function(){ return 0; }; } else { return new Polygon(sides); } } function Rectangle(width, height){ Polygon.call(this, 2); //返回一個新的Polygon對象,裏面的屬性方法不會成爲Rectangle的屬性和方法 this.width = width; this.height = height; this.getArea = function(){ return this.width * this.height; }; } ---------------------------------------------------- var rect = new Rectangle(5, 10); alert(rect.sides); //undefined ---------------------------------------------------- Rectangle.prototype = new Polygon(); //使得,一個Rectangle實例也同時是一個Polygon實例 var rect = new Rectangle(5, 10); alert(rect.sides); //2
//法一: //在第一次調用的過程當中,該函數會被覆蓋爲另一個按合適方式執行的函數, //這樣任何對原函數的調用都不用再通過執行的分支了 function createXHR(){ if (typeof XMLHttpRequest != "undefined"){ createXHR = function(){ return new XMLHttpRequest(); }; } else if (typeof ActiveXObject != "undefined"){ createXHR = function(){ if (typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i, len; for (i=0,len=versions.length; i < len; i++){ try { new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; break; } catch (ex){ //skip } } } return new ActiveXObject(arguments.callee.activeXString); }; } else { createXHR = function(){ throw new Error("No XHR object available."); }; } return createXHR(); }
//第二種實現惰性載入的方式是在聲明函數時就指定適當的函數。 //這樣,第一次調用函數時就不會損 失性能了,而在代碼首次加載時會損失一點性能 var createXHR = (function(){ if (typeof XMLHttpRequest != "undefined"){ return function(){ return new XMLHttpRequest(); }; } else if (typeof ActiveXObject != "undefined"){ return function(){ if (typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i, len; for (i=0,len=versions.length; i < len; i++){ try { new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; break; } catch (ex){ //skip } } } return new ActiveXObject(arguments.callee.activeXString); }; } else { return function(){ throw new Error("No XHR object available."); }; } })();
function bind(fn, context){ return function(){ return fn.apply(context, arguments); }; } //注意這裏使用的 arguments 對象是內部函 數的,而非 bind()的。 //當調用返回的函數時,它會在給定環境中執行被傳入的函數並給出全部參數 var handler = { message: "Event handled", handleClick: function(event){ alert(this.message + ":" + event.type); } }; //自定義的bind var btn = document.getElementById("my-btn"); EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler)); //原生的 bind()方法 //不用 再本身定義 bind()函數了,而是能夠直接在函數上調用這個方法 var btn = document.getElementById("my-btn"); EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler));
var person = { name: "Nicholas" }; Object.preventExtensions(person); person.age = 29; alert(person.age); //undefined //------------------------------------------------ var person = { name: "Nicholas" }; alert(Object.isExtensible(person)); //true Object.preventExtensions(person); alert(Object.isExtensible(person)); //false
var person = { name: "Nicholas" }; alert(Object.isExtensible(person)); //true alert(Object.isSealed(person)); //false Object.seal(person); alert(Object.isExtensible(person)); //false alert(Object.isSealed(person)); //true
setTimeout(function(){ //處理中 setTimeout(arguments.callee, interval); }, interval); //這個模式鏈式調用了 setTimeout(),每次函數執行的時候都會建立一個新的定時器。 //第二個 setTimeout()調用使用了 arguments.callee 來獲取對當前執行的函數的引用,併爲其設置另一個定時器。 //這樣作的好處是,在前一個定時器代碼執行完以前,不會向隊列插入新的定時器代碼,確保 不會有任何缺失的間隔。 //並且,它能夠保證在下一次定時器代碼執行以前,至少要等待指定的間隔,避免了連續的運行。
//基本模式 setTimeout(function(){ //取出下一個條目並處理 var item = array.shift(); process(item); //若還有條目,再設置另外一個定時器 if(array.length > 0){ setTimeout(arguments.callee, 100); } }, 100) function chunk(array, process, context){ setTimeout(function(){ var item = array.shift(); process.call(context, item); if (array.length > 0){ setTimeout(arguments.callee, 100); } }, 100); }
//基本模式 var processor = { timeoutId: null, //實際進行處理的方法 performProcessing: function(){ //實際執行的代碼 }, //初始處理調用的方法 process: function(){ clearTimeout(this.timeoutId); var that = this; this.timeoutId = setTimeout(function(){ that.performProcessing(); }, 100); } }; //嘗試開始執行 processor.process();
//簡化版(使用 throttle()函數) function throttle(method, context) { clearTimeout(method.tId); method.tId= setTimeout(function(){ method.call(context); }, 100); }
function EventTarget(){ this.handlers = {}; //用於儲存事件處理程序 } EventTarget.prototype = { constructor: EventTarget, addHandler: function(type, handler){ //法接受兩個參數:事件類型和用於處理該事件的函數 if (typeof this.handlers[type] == "undefined"){ //handlers 屬性中是否已經存在一個針對該事件類型的數組 this.handlers[type] = []; //;若是沒有,則建立一個新的數組 } this.handlers[type].push(handler); //使用 push()將該處理程序添加到數組的末尾。 }, fire: function(event){ //接受一個單獨的參數,是一個至少包含 type 屬性的對象。 if (!event.target){ //給 event 對象設置一個 target 屬性 event.target = this; } if (this.handlers[event.type] instanceof Array){ var handlers = this.handlers[event.type]; for (var i=0, len=handlers.length; i < len; i++){ handlers[i](event); } } }, removeHandler: function(type, handler){ //接受事件的類型和事件處理程序 if (this.handlers[type] instanceof Array){ var handlers = this.handlers[type]; //這個方法搜索事件處理程序的數組找到要刪除的處理程序的位置 for (var i=0, len=handlers.length; i < len; i++){ if (handlers[i] === handler){ break; } } handlers.splice(i, 1); } } };
拖放的基本概念很簡單:建立一個絕對定位的元素,使其能夠用鼠標移動javascript
var DragDrop = function(){ var dragging = null; diffX = 0; diffY = 0; function handleEvent(event){ //獲取事件和目標 event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); //肯定事件類型 switch(event.type){ case "mousedown": if (target.className.indexOf("draggable") > -1){ dragging = target; diffX = event.clientX - target.offsetLeft; diffY = event.clientY - target.offsetTop; } break; case "mousemove": if (dragging !== null){ //指定位置 dragging.style.left = (event.clientX - diffX) + "px"; dragging.style.top = (event.clientY - diffY) + "px"; } break; case "mouseup": dragging = null; break; } }; //公共接口 return { enable: function(){ EventUtil.addHandler(document, "mousedown", handleEvent); EventUtil.addHandler(document, "mousemove", handleEvent); EventUtil.addHandler(document, "mouseup", handleEvent); }, disable: function(){ EventUtil.removeHandler(document, "mousedown", handleEvent); EventUtil.removeHandler(document, "mousemove", handleEvent); EventUtil.removeHandler(document, "mouseup", handleEvent); } } }();
//這一章看得我眼珠子都要掉了,難頂,緩一緩再二刷叭~java