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