JavaScript一些方法的实现

180 阅读1分钟

首先在Function的原型对象上定义一个method方法,本文贯彻始终都会用到这个方法,该方法定义如下:

Function.prototype.method = function(name,func){    
    this.prototype[name] = func;    
    return this;
}

数组方法

splice方法

Array.method('splice', function(start, deleteCount){
    var max = Math.max,        
    min = Math.min,        
    delta,        
    element,        
    insertCount = max(arguments.length - 2, 0),        
    k = 0,        
    len = this.length,        
    new_len,        
    result = [],        
    shift_count;    
    start = start || 0;    
    if (start < 0) {
        start += len;    
    }
    start = max(min(start, len), 0);    
    deleteCount = max(min(typeof deleteCount === 'number' ? deleteCount : len, len - start), 0);    
    delta = insertCount - deleteCount;    
    new_len = len + delta;    
    while (k < deleteCount) {        
        element = this[start + k];        
        if (element !== undefined) {            
            result[k] = element;        
        }        
        k += 1;    
    }    
    shift_count = len - start - deleteCount;    
    if (delta < 0) {        
        k = start + insertCount;        
        while (shift_count) {            
            this[k] = this[k - delta];            
            k += 1;            
            shift_count -= 1;        
        }        
        this.length = new_len;    
    } else if (delta > 0) {       
        k = 1;        
        while (shift_count) {            
            this[new_len - k] = this[len - k];           
            k += 1;            
            shift_count -= 1;        
        }    
    }    
    for (k = 0; k < insertCount; k += 1) {        
        this[start + k] = arguments[k + 2];    
    }    
    return result;
})

pop方法

Array.method('pop', function(){
    return this.splice(this.length - 1, 1)[0];
})

push方法

Array.method('push', function(){
    this.splice.apply(this,[this.length, 0].concat(Array.prototype.slice.apply(arguments)));
    return this.length;
})

shift方法

Array.method('shift', function(){
    return this.splice(0,1)[0];
})

unshift方法

Array.method('unshift', function(){
    this.splice.apply(this, [0, 0].concat(Array.prototype.slice.apply(arguments)));
    return this.length;
})

filter方法

Array.method('filter', function(callback){
    if (Object.prototype.toString.call(this) !== '[object Array]' || !this.length || typeof callback !== 'function') {
        return [];
    } else {
        const result = [];
        for (let i = 0; i < this.length; i++) {
            const item = this[i];
            if (callback(item, i, this)) {
                result.push(item);
            }
        };
        return result;
    }
})

find方法

Array.method('find', function(callback){
    if (Object.prototype.toString.call(this) !== '[object Array]' || !this.length || typeof callback !== 'function') {
        return;
    } else {
        for (let i = 0; i < this.length; i++) {
            const item = this[i];
            if (callback(item,i,this)) {
                return item;
            }
        }
    }
})

findIndex方法

Array.method('findIndex', function(callback){
    if (Object.prototype.toString.call(this) !== '[object Array]' || !this.length || typeof callback !== 'function') {
        return;
    } else {
        for (let i = 0; i < this.length; i++) {
            const item = this[i];
            if (callback(item, i, this)) {
                return i;
            }
        }
    }
})

map方法

Array.method('map', function(callback){
    // 处理数组类型异常  
    if(this === null || this === undefined) {
        throw new TypeError("Cannot read property 'map' of null or undefined");
    };
    if(Object.prototype.toString.call(callback) !== '[object Function]'){
        throw new TypeError(callback + "is not a function");
    };
    const result = [];
    for(let i = 0; i < this.length; i++) {
        const item = this[i];
        const newItem = callback(item, i, this);
        result.push(newItem);
    }
    return result;
})

函数方法

call方法

call方法的简单实现

Function.method('call',function(obj, ...args){
    const fn = Symbol();
    obj[fn] = this;
    obj[fn](...args);
    delete obj[fn];
})

apply方法

apply方法的简单实现:apply方法几乎和call方法一样,不同的是apply方法传入的是一个数组

Function.method('apply',function(obj,args){
    const fn = Symbol();
    obj[fn] = this;
    obj[fn](...args);
    delete obj[fn];
})

bind方法

Function.method('bind', function(that){
    //返回一个函数,调用这个函数就像它是那个对象的方法一样
    const method = this,
    slice = Array.prototype.slice,
    args = slice.apply(arguments, [1]);
    return function(){
        return method.apply(that, args.concat(slice.apply(arguments, [0])))
    }
})

参考资料:javaScript语言精髓