前端面试宝典之手写代码篇

手写事件侦听器,并要求兼容浏览器

var eventUtil = {
    getEvent: function (event) {
        return event || window.event;
    },
    getTarget: function (event) {
        return event.target || event.srcElement;
    },
    addListener: function (element, type, hander) {
        if (element.addEventListener) {
            element.addEventListener(type, hander, false);
        } else if (element.attachEvent) {
            element.attachEvent('on' + type, hander);
        } else {
            element['on' + type] = hander;
        }
    },
    removeListener: function (element, type, hander) {
        if (element.removeEventListener) {
            element.removeEventListener(type, hander, false);
        } else if (element.deattachEvent) {
            element.detachEvent(type, hander);
        } else {
            element['on' + type] = null;
        }
    },
    preventDefault: function (event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    stopPropagation: function (event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    }
}; // 调用(function() {  var btn = document.getElementById("btn");  var link = document.getElementsByTagName("a")[0];

eventUtil.addListener(btn, "click", function (event) {
    var event = eventUtil.getEvent(event);
    var target = eventUtil.getTarget(event);
    alert(event.type);
    alert(target);
    eventUtil.stopPropagation(event);
});

eventUtil.addListener(link, "click", function (event) {
    alert("prevent default event");
    var event = eventUtil.getEvent(event);
    eventUtil.preventDefault(event);
});

eventUtil.addListener(document.body, "click", function () {
    alert("click body");
});

手写事件模型

var Event = (function () {
    var list = {},
        bind, trigger, remove;
    bind = function (key, fn) {
        if (!list[key]) {
            list[key] = [];
        }
        list[key].push(fn);
    };
    trigger = function () {
        var key = Array.prototype.shift.call(arguments);
        var fns = list[key];
        if (!fns || fns.length === 0) {
            return false;
        }
        for (var i = 0, fn; fn = fns[i++];) {
            fn.apply(this, arguments);
        }
    };
    remove = function (key, fn) {
        var fns = list[key];
        if (!fns) {
            return false;
        }
        if (!fn) {
            fns & (fns.length = 0);
        } else {
            for (var i = fns.length - 1; i >= 0; i--) {
                var _fn = fns[i];
                if (_fn === fn) {
                    fns.splice(i, 1);
                }
            }
        }
    };
    return {
        bind: bind,
        trigger: trigger,
        remove: remove
    }
})(); // 调用
Event.bind('Hit', function () {
    console.log('bind event');
}); // 绑定事件
Event.trigger("Hit", function () {
    console.log('trigger event');
}); // 触发事件

手写事件代理,并要求兼容浏览器

function delegateEvent(parentEl, selector, type, fn) {
    var handler = function (e) {
        var e = e || window.event;
        var target = e.target || e.srcElement;
        if (matchSelector(target, selector)) {
            if (fn) {
                fn.call(target, e);
            }
        }
    };
    if (parentEl.addEventListener) {
        parentEl.addEventListener(type, handler);
    } else {
        parentEl.attachEvent("on" + type, handler);
    }
}
/**
 * support #id, tagName, .className
 */
function matchSelector(ele, selector) { // if use id
    if (selector.charAt(0) === "#") {
        return ele.id === selector.slice(1);
    } // if use class
    if (selector.charAt(0) === ".") {
        return (" " + ele.className + " ").indexOf(" " + selector.slice(1) + " ") != -1;
    } // if use tagName
    return ele.tagName.toLowerCase() === selector.toLowerCase();
} // 调用var box = document.getElementById("box");
delegateEvent(box, "a", "click", function () {
    console.log(this.href);
})

手写事件触发器,并要求兼容浏览器

var fireEvent = function (element, event) {
    if (document.createEventObject) {
        var mockEvent = document.createEventObject();
        return element.fireEvent('on' + event, mockEvent)
    } else {
        var mockEvent = document.createEvent('HTMLEvents');
        mockEvent.initEvent(event, true, true);
        return element.dispatchEvent(mockEvent);
    }
}

手写 Function.bind 函数

if (!Function.prototype.bind) {
    Function.prototype.bind = function (oThis) {
        if (typeof this !== "function") {
            throw new TypeError("'this' is not function");
        } // bind's default arguments, array without first element
        // first part arguments for the function
        var aBindArgs = Array.prototype.slice.call(arguments, 1);
        var fToBind = this; // the function will be binding
        var fNOP = function () {};
        var fBound = function () { // target this will be binding
            var oThis = this instanceof fNOP ? this : oThis || this; // last part arguments for the function
            var aCallArgs = Array.prototype.slice.call(arguments); // complete arguments for the function
            var aFuncArgs = aBindArgs.concat(aCallArgs);
            return fToBind.apply(oThis, aFuncArgs);
        }; // fBound extends fToBind
        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();
        return fBound;
    };
} // 调用
var add = function (a, b, c) {
    return a + b + c;
};
var newAdd = add.bind(null, 1, 2);
var result = newAdd(3);

手写数组快速排序

var quickSort = function (arr) {
    if (arr.length <= 1) {
        return arr;
    }
    var pivotIndex = Math.floor(arr.length / 2);
    var pivot = arr.splice(pivotIndex, 1)[0];
    var left = [];
    var right = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        if (arr[i] < pivot) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }
    }
    return quickSort(left).concat([pivot], quickSort(right));
};
// 调用
quickSort([9, 4, 2, 8, 1, 5, 3, 7]);

手写数组冒泡排序

var bubble = function (arr) {
    var maxIndex = arr.length - 1,
        temp, flag;
    for (var i = maxIndex; i > 0; i--) {
        flag = true
        for (var j = 0; j < i; j++) {
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = false;
            }
        }
        if (!flag) {
            break;
        }
    }
    return arr;
}
// 调用
var arr = bubble([13, 69, 28, 93, 55, 75, 34]);

手写数组去重

Array.prototype.unique = function () {
    return [...new Set(this)];
};
// 调用
[1, 2, 3, 3, 2, 1].unique();

function unique1(arr) {
    var hash = {},
        result = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        if (!hash[arr[i]]) {
            result.push(arr[i]);
            hash[arr[i]] = true;
        }
    }
    return result;
}
// 调用
unique1([1, 2, 3, 3, 2, 1]);
Array.prototype.unique2 = function () {
    this.sort();
    var result = [this[0]];
    var len = this.length;
    for (var i = 0; i < len; i++) {
        if (this[i] !== result[result.length - 1]) {
            result.push(this[i]);
        }
    }
    return result;
}
// 调用
[1, 2, 3, 3, 2, 1].unique2();

function unique3(arr) {
    var result = [];
    for (var i = 0; i < arr.length; i++) {
        if (result.indexOf(arr[i]) == -1) {
            result.push(arr[i]);
        }
    }
    return result;
}
// 调用
unique3([1, 2, 3, 3, 2, 1]);

将url的查询参数解析成字典对象

function parseQuery(url) {
    url = url == null ? window.location.href : url;
    var search = url.substring(url.lastIndexOf("?") + 1);
    var hash = {};
    var reg = /([^?&=]+)=([^?&=]*)/g;
    search.replace(reg, function (match, $1, $2) {
        var name = decodeURIComponent($1);
        var val = decodeURIComponent($2);
        hash[name] = String(val);
        return match;
    });
    return hash;
}

封装函数节流函数

var throttle = function (fn, delay, mustRunDelay) {
    var timer = null;
    var t_start;
    return function () {
        var context = this,
            args = arguments,
            t_curr = +new Date();
        clearTimeout(timer);
        if (!t_start) {
            t_start = t_curr;
        }
        if (t_curr - t_start >= mustRunDelay) {
            fn.apply(context, args);
            t_start = t_curr;
        } else {
            timer = setTimeout(function () {
                fn.apply(context, args);
            }, delay);
        }
    };
};
// 调用(两次间隔50ms内连续触发不执行,但每累计100ms至少执行一次
window.onresize = throttle(myFunc, 50, 100);

用JS实现千位分隔符

function test1(num) {
    var str = (+num) + '';
    var len = str.length;
    if (len <= 3) return str;
    num = '';
    while (len > 3) {
        len -= 3;
        num = ',' + str.substr(len, 3) + num;
    }
    return str.substr(0, len) + num;
}

function test2(num) { // ?= 正向匹配:匹配位置
    // ?! 正向不匹配:排除位置
    var str = (+num).toString();
    var reg = /(?=(?!\b)(\d{3})+$)/g;
    return str.replace(reg, ',');
}

猜你喜欢

转载自blog.csdn.net/Corey_mengxiaodong/article/details/84621962