编程能力
-
手写事件侦听器,并要求兼容浏览器
1var eventUtil = { 2 getEvent: function(event) { 3 return event || window.event; 4 }, 5 6 getTarget: function(event) { 7 return event.target || event.srcElement; 8 }, 9 10 addListener: function(element, type, hander) { 11 if (element.addEventListener) { 12 element.addEventListener(type, hander, false); 13 } else if (element.attachEvent) { 14 element.attachEvent('on' + type, hander); 15 } else { 16 element['on' + type] = hander; 17 } 18 }, 19 20 removeListener: function(element, type, hander) { 21 if (element.removeEventListener) { 22 element.removeEventListener(type, hander, false); 23 } else if (element.deattachEvent) { 24 element.detachEvent(type, hander); 25 } else { 26 element['on' + type] = null; 27 } 28 }, 29 30 preventDefault: function(event) { 31 if (event.preventDefault) { 32 event.preventDefault(); 33 } else { 34 event.returnValue = false; 35 } 36 }, 37 38 stopPropagation: function(event) { 39 if (event.stopPropagation) { 40 event.stopPropagation(); 41 } else { 42 event.cancelBubble = true; 43 } 44 } 45}; 46 47 // 调用 48 (function() { 49 var btn = document.getElementById("btn"); 50 var link = document.getElementsByTagName("a")[0]; 51 52 eventUtil.addListener(btn, "click", function(event) { 53 var event = eventUtil.getEvent(event); 54 var target = eventUtil.getTarget(event); 55 alert(event.type); 56 alert(target); 57 eventUtil.stopPropagation(event); 58 }); 59 60 eventUtil.addListener(link, "click", function(event) { 61 alert("prevent default event"); 62 var event = eventUtil.getEvent(event); 63 eventUtil.preventDefault(event); 64 }); 65 66 eventUtil.addListener(document.body, "click", function() { 67 alert("click body"); 68 }); 69})(); -
手写事件模型
1var Event = (function () { 2 var list = {}, bind, trigger, remove; 3 bind = function (key, fn) { 4 if (!list[key]) { 5 list[key] = []; 6 } 7 list[key].push(fn); 8 }; 9 trigger = function () { 10 var key = Array.prototype.shift.call(arguments); 11 var fns = list[key]; 12 if (!fns || fns.length === 0) { 13 return false; 14 } 15 for (var i = 0, fn; fn = fns[i++];) { 16 fn.apply(this, arguments); 17 } 18 }; 19 remove = function (key, fn) { 20 var fns = list[key]; 21 if (!fns) { 22 return false; 23 } 24 if (!fn) { 25 fns & (fns.length = 0); 26 } else { 27 for (var i = fns.length - 1; i >= 0; i--) { 28 var _fn = fns[i]; 29 if (_fn === fn) { 30 fns.splice(i, 1); 31 } 32 } 33 } 34 }; 35 return { 36 bind: bind, 37 trigger: trigger, 38 remove: remove 39 } 40})(); 41 42// 调用 43Event.bind('Hit', function(){ console.log('bind event'); }); // 绑定事件 44Event.trigger("Hit", function(){ console.log('trigger event'); }); // 触发事件 -
手写事件代理,并要求兼容浏览器
1function delegateEvent(parentEl, selector, type, fn) { 2 var handler = function(e){ 3 var e = e || window.event; 4 var target = e.target || e.srcElement; 5 if (matchSelector(target, selector)) { 6 if(fn) { 7 fn.call(target, e); 8 } 9 } 10 }; 11 if(parentEl.addEventListener){ 12 parentEl.addEventListener(type, handler); 13 }else{ 14 parentEl.attachEvent("on" + type, handler); 15 } 16} 17/** 18 * support #id, tagName, .className 19 */ 20function matchSelector(ele, selector) { 21 // if use id 22 if (selector.charAt(0) === "#") { 23 return ele.id === selector.slice(1); 24 } 25 // if use class 26 if (selector.charAt(0) === ".") { 27 return (" " + ele.className + " ").indexOf(" " + selector.slice(1) + " ") != -1; 28 } 29 // if use tagName 30 return ele.tagName.toLowerCase() === selector.toLowerCase(); 31} 32 33// 调用 34var box = document.getElementById("box"); 35delegateEvent(box, "a", "click", function(){ 36 console.log(this.href); 37}) -
手写事件触发器,并要求兼容浏览器
1var fireEvent = function(element, event){ 2 if (document.createEventObject){ 3 var mockEvent = document.createEventObject(); 4 return element.fireEvent('on' + event, mockEvent) 5 }else{ 6 var mockEvent = document.createEvent('HTMLEvents'); 7 mockEvent.initEvent(event, true, true); 8 return element.dispatchEvent(mockEvent); 9 } 10} -
手写 Function.bind 函数
1if (!Function.prototype.bind) { 2 Function.prototype.bind = function (oThis) { 3 if (typeof this !== "function") { 4 throw new TypeError("'this' is not function"); 5 } 6 7 // bind's default arguments, array without first element 8 // first part arguments for the function 9 var aBindArgs = Array.prototype.slice.call(arguments, 1); 10 var fToBind = this; // the function will be binding 11 var fNOP = function () {}; 12 var fBound = function () { 13 // target this will be binding 14 var oThis = this instanceof fNOP ? this : oThis || this; 15 // last part arguments for the function 16 var aCallArgs = Array.prototype.slice.call(arguments); 17 // complete arguments for the function 18 var aFuncArgs = aBindArgs.concat(aCallArgs); 19 return fToBind.apply(oThis, aFuncArgs); 20 }; 21 22 // fBound extends fToBind 23 fNOP.prototype = this.prototype; 24 fBound.prototype = new fNOP(); 25 26 return fBound; 27 }; 28} 29 30// 调用 31var add = function(a, b, c){ return a + b + c;}; 32var newAdd = add.bind(null, 1, 2); 33var result = newAdd(3); -
手写数组快速排序
1var quickSort = function(arr) { 2 if (arr.length <= 1) { return arr; } 3 var pivotIndex = Math.floor(arr.length / 2); 4 var pivot = arr.splice(pivotIndex, 1)[0]; 5 var left = []; 6 var right = []; 7 for (var i = 0, len = arr.length; i < len; i++){ 8 if (arr[i] < pivot) { 9 left.push(arr[i]); 10 } else { 11 right.push(arr[i]); 12 } 13 } 14 return quickSort(left).concat([pivot], quickSort(right)); 15}; 16 17// 调用 18quickSort([9, 4, 2, 8, 1, 5, 3, 7]); -
手写数组冒泡排序
1var bubble = function(arr){ 2 var maxIndex = arr.length - 1, temp, flag; 3 for (var i = maxIndex; i > 0; i--) { 4 flag = true 5 for (var j = 0; j < i; j++) { 6 if (arr[j] > arr[j + 1]) { 7 temp = arr[j]; 8 arr[j] = arr[j + 1]; 9 arr[j + 1] = temp; 10 flag = false; 11 } 12 } 13 if(! flag){ 14 break; 15 } 16 } 17 return arr; 18} 19// 调用 20var arr = bubble([13, 69, 28, 93, 55, 75, 34]); -
手写数组去重
1Array.prototype.unique = function() { return [...new Set(this)];}; 2// 调用 3[1, 2, 3, 3, 2, 1].unique(); 4 5function unique1(arr){ 6 var hash = {}, result = []; 7 for(var i=0, len=arr.length; i<len; i++){ 8 if(! hash[arr[i]]){ 9 result.push(arr[i]); 10 hash[arr[i]] = true; 11 } 12 } 13 return result; 14} 15// 调用 16unique1([1, 2, 3, 3, 2, 1]); 17 18Array.prototype.unique2 = function(){ 19 this.sort(); 20 var result = [this[0]]; 21 var len = this.length; 22 for(var i = 0; i < len; i++){ 23 if(this[i] !== result[result.length - 1]){ 24 result.push(this[i]); 25 } 26 } 27 return result; 28} 29// 调用 30[1, 2, 3, 3, 2, 1].unique2(); 31 32function unique3(arr){ 33 var result = []; 34 for(var i=0; i<arr.length; i++){ 35 if(result.indexOf(arr[i]) == -1){ 36 result.push(arr[i]); 37 } 38 } 39 return result; 40} 41 42// 调用 43unique3([1, 2, 3, 3, 2, 1]); -
将url的查询参数解析成字典对象
1function parseQuery(url) { 2 url = url == null ? window.location.href : url; 3 var search = url.substring(url.lastIndexOf("?") + 1); 4 var hash = {}; 5 var reg = /([^?&=]+)=([^?&=]*)/g; 6 search.replace(reg, function (match, $1, $2) { 7 var name = decodeURIComponent($1); 8 var val = decodeURIComponent($2); 9 hash[name] = String(val); 10 return match; 11 }); 12 return hash; 13} -
封装函数节流函数
1var throttle = function(fn, delay, mustRunDelay){ 2 var timer = null; 3 var t_start; 4 return function(){ 5 var context = this, args = arguments, t_curr = +new Date(); 6 clearTimeout(timer); 7 if(!t_start){ 8 t_start = t_curr; 9 } 10 if(t_curr - t_start >= mustRunDelay){ 11 fn.apply(context, args); 12 t_start = t_curr; 13 } else { 14 timer = setTimeout(function(){ 15 fn.apply(context, args); 16 }, delay); 17 } 18 }; 19}; 20 21// 调用(两次间隔50ms内连续触发不执行,但每累计100ms至少执行一次 22window.onresize = throttle(myFunc, 50, 100); -
用JS实现千位分隔符
1function test1(num){ 2 var str = (+ num) + ''; 3 var len = str.length; 4 if(len <= 3) return str; 5 num = ''; 6 while(len > 3){ 7 len -= 3; 8 num = ',' + str.substr(len, 3) + num; 9 } 10 return str.substr(0, len) + num; 11} 12 13function test2(num){ 14 // ?= 正向匹配:匹配位置 15 // ?! 正向不匹配:排除位置 16 var str = (+num).toString(); 17 var reg = /(?=(?!\b)(\d{3})+$)/g; 18 return str.replace(reg, ','); 19}
