前端手写代码大全

1, apply

code

Function.prototype.myApply = function () {
    let thisObj = arguments[0] || window;
    let args = arguments[1];
    thisObj.fn = this;
    let res = thisObj.fn(...args);
    delete thisObj.fn;
    return res;
}
复制代码

test:

2, call

code

Function.prototype.myCall = function () {
    let thisObj = arguments[0] || window;
    let args = [...arguments].slice(1);
    thisObj.fn = this;
    let res = thisObj.fn(...args);
    delete thisObj.fn;
    return res;
}
复制代码

test:

3, bind

code:

Function.prototype.myBind = function () {
   let thisObj = arguments[0] || window;
   let fn = this;
   let args = [...arguments].slice(1);
   return function F () {
       if (this instanceof F) {
           return new fn(...args, ...arguments)
       } else {
           return fn.apply(thisObj, args.concat([...arguments]));
       }
   }
}
复制代码

test

4, 节流

code

function throttle (fn, time) {
    let startTime = +new Date();
    return function F () {
        let lastTime = +new Date();
        if (lastTime - startTime >= time) {
            fn.apply(this, [...arguments]);
            startTime = lastTime;
        }
    }
}
复制代码

test

5, 防抖

code

function antiShake (fn, time, immediate) {
    let time = null;
    return function F () {
        if (immediate) {
           fn.apply(this, [...arguments]);
        }
        if (time) {
            clearInterval(time);
        }
        setInterval(function () {
            fn.apply(this, [...arguments]);
        }, time);
    }
}
复制代码

6, 继承

code

 function Animal(name) {
     this.name = name;
 }
 Animal.prototype.say = function () {
     console.log('my name is:' + this.name);
 }
 function Dog(name, age) {
     Animal.apply(this, [name]);
     this.age = age;
 }
 Dog.prototype = Object.create(Animal.prototype, {
     constructor: {
         value: Dog,
         enumable: false,
         writable: true,
         configurable: true
     }
 });
 var a = new Dog('xiaowang', 1)
复制代码

code

7, instanceof

code

function myInstanceof(left, right) {
    var r = right.prototype;
    left = left.__proto__;
    while(true) {
        if (left === null) {
            return false;
        } else if (left === r) {
            return true;
        }
        left = left.__proto__;
    }
}
复制代码

test

8, new

code

  function myNew(fn, ...args) {
      let obj = {};
      obj.__proto__ = fn.prototype;
      var res = fn.apply(obj, args);
      return res instanceof Object ? res : obj;
  }
复制代码

test

9, 柯里化

code

function currying (fn, ...args) {
    if (fn.length <= args.length) {
        return fn(...args);
    }
    return function F() {
        return currying(fn, ...args, ...arguments);
    }
}
复制代码

test

10,深拷贝

方法1

code

JSON.parse(JSON.stringify(obj))
复制代码

test

缺点:

  1. 函数无法序列化
  2. 无法解决循环嵌套
  3. underfined 无法序列化
  4. symbol 无法序列化

##方法2

code

function messageChannelClone(obj) {
    return new Promise((resolve, reject) => {
        const {port1, port2} = new MessageChannel();
        port2.onmessage = res => resolve(res.data);
        port1.postMessage(obj);
    })
}
var b = {
    info: {
        name: 'jin'
    }
}
messageChannelClone(b).then(res=>{
    console.log(res);
})
复制代码

test

缺点:

  1. 函数无法序列化
  2. symbol 无法序列化

方法3 使用—lodash库

方法4 自己简单模拟实现

code

function clone(obj) {
    let res;
    if (obj && obj instanceof Object) {
        res = Array.isArray(obj) ? [] : {};
        for (let item in obj) {
            res[i] = obj[item] instanceof Object ? clone(obj[item]) : obj[item];
        }
    } else {
        res = obj;
    }
    return res;
}
复制代码

11,JSON.parse

方法1

code

var a = '{name: "jiweijin"}'
eval('(' + a + ')')
复制代码

方法2

var a = '{name: "jiweijin"}'
new Function('return ' + a)()
复制代码

12,JSON.stringify

code

function jsonStringify(obj) {
    let type = typeof obj;
    if (type !== "object") {
        if (/string|undefined|function/.test(type)) {
            obj = '"' + obj + '"';
        }
        return String(obj);
    } else {
        let json = []
        let arr = Array.isArray(obj)
        for (let k in obj) {
            let v = obj[k];
            let type = typeof v;
            if (/string|undefined|function/.test(type)) {
                v = '"' + v + '"';
            } else if (type === "object") {
                v = jsonStringify(v);
            }
            json.push((arr ? "" : '"' + k + '":') + String(v));
        }
        return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}")
    }
}
复制代码

13,ajax

code

简单版

function myHttp(opt) {
  let url = opt.url || '';
  let method = opt.method || 'POST';
  let data = opt.data || {};
  let http = new XMLHttpRequest();
  if (method.toUpperCase === 'GET') {
    var dataStr = '';
    for (let item in data) {
        dataStr += item + '=' + data[item];
    }
    url += '?' + dataStr;
    http.open(method, url);
    http.send(null)
  } else {
     http.open(method, url)
     http.send(data)
  }
  http.onreadystatechange = function () {
      if (http.readystate === 4 && http.status === 200) {
          opt.success(http.responseText)
      }
  }
}

复制代码

14,promise

code

/**
 * 1. new Promise时,需要传递一个 executor 执行器,执行器立刻执行
 * 2. executor 接受两个参数,分别是 resolve 和 reject
 * 3. promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
 * 4. promise 的状态一旦确认,就不会再改变
 * 5. promise 都有 then 方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, 
 *      和 promise 失败的回调 onRejected
 * 6. 如果调用 then 时,promise已经成功,则执行 onFulfilled,并将promise的值作为参数传递进去。
 *      如果promise已经失败,那么执行 onRejected, 并将 promise 失败的原因作为参数传递进去。
 *      如果promise的状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次将对应的函数执行(发布订阅)
 * 7. then 的参数 onFulfilled 和 onRejected 可以缺省
 * 8. promise 可以then多次,promise 的then 方法返回一个 promise
 * 9. 如果 then 返回的是一个结果,那么就会把这个结果作为参数,传递给下一个then的成功的回调(onFulfilled)
 * 10. 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调(onRejected)
 * 11.如果 then 返回的是一个promise,那么需要等这个promise,那么会等这个promise执行完,promise如果成功,
 *   就走下一个then的成功,如果失败,就走下一个then的失败
 */

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promise(executor) {
    let self = this;
    self.status = PENDING;
    self.onFulfilled = [];//成功的回调
    self.onRejected = []; //失败的回调
    //PromiseA+ 2.1
    function resolve(value) {
        if (self.status === PENDING) {
            self.status = FULFILLED;
            self.value = value;
            self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1
        }
    }

    function reject(reason) {
        if (self.status === PENDING) {
            self.status = REJECTED;
            self.reason = reason;
            self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2
        }
    }

    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

Promise.prototype.then = function (onFulfilled, onRejected) {
    //PromiseA+ 2.2.1 / PromiseA+ 2.2.5 / PromiseA+ 2.2.7.3 / PromiseA+ 2.2.7.4
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
    let self = this;
    //PromiseA+ 2.2.7
    let promise2 = new Promise((resolve, reject) => {
        if (self.status === FULFILLED) {
            //PromiseA+ 2.2.2
            //PromiseA+ 2.2.4 --- setTimeout
            setTimeout(() => {
                try {
                    //PromiseA+ 2.2.7.1
                    let x = onFulfilled(self.value);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    //PromiseA+ 2.2.7.2
                    reject(e);
                }
            });
        } else if (self.status === REJECTED) {
            //PromiseA+ 2.2.3
            setTimeout(() => {
                try {
                    let x = onRejected(self.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        } else if (self.status === PENDING) {
            self.onFulfilled.push(() => {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(self.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            });
            self.onRejected.push(() => {
                setTimeout(() => {
                    try {
                        let x = onRejected(self.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            });
        }
    });
    return promise2;
}

function resolvePromise(promise2, x, resolve, reject) {
    let self = this;
    //PromiseA+ 2.3.1
    if (promise2 === x) {
        reject(new TypeError('Chaining cycle'));
    }
    if (x && typeof x === 'object' || typeof x === 'function') {
        let used; //PromiseA+2.3.3.3.3 只能调用一次
        try {
            let then = x.then;
            if (typeof then === 'function') {
                //PromiseA+2.3.3
                then.call(x, (y) => {
                    //PromiseA+2.3.3.1
                    if (used) return;
                    used = true;
                    resolvePromise(promise2, y, resolve, reject);
                }, (r) => {
                    //PromiseA+2.3.3.2
                    if (used) return;
                    used = true;
                    reject(r);
                });

            }else{
                //PromiseA+2.3.3.4
                if (used) return;
                used = true;
                resolve(x);
            }
        } catch (e) {
            //PromiseA+ 2.3.3.2
            if (used) return;
            used = true;
            reject(e);
        }
    } else {
        //PromiseA+ 2.3.3.4
        resolve(x);
    }
}


复制代码

转载于:https://juejin.im/post/5cb423f56fb9a06856568104

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值