js手写题

call apply bind

let obj = { name: "hello" };
let t = {
  fn: function (a, b) {
    console.log(this);
    console.log(a);
    console.log(b);
    return a
  },
};
Function.prototype._call = function(context, ...arg){
    context = context || window
    context._fn = this
    let res = context._fn(...arg)
    delete context._fn
    return res
}
t.fn._call(obj, 1, 2)

// apply ...arg接收参数不同
Function.prototype.myApply = function (context, arg) {
  context = context || window;

  context.__fn = this;
  var res = context.__fn(...arg);
  delete context.__fn;
  return res;
};
t.fn.myApply(obj, [1, 2])


Function.prototype._bind = function(context, ...arg){
    context = context || window
    context._fn = this
    return function(...inner){
        let res = context._fn(...arg, ...inner)
        delete context._fn
        return res
    }
}
let fn = t.fn._bind(obj, 'hh')

new

function Person(a){
    this.a = a
    // return {haha: 444}
}

function _new(Ctor, ...arg){
    if(typeof constructor !== 'function'){
        throw TypeError
    }
    let obj = Object.create(Ctor.prototype)
    let res = Ctor.apply(obj, arg)
    return res && typeof res === 'object' ? res : obj
}
var p = _new(Person, 2)
console.log(p)

ajax

let xhr = new XMLHttpRequest()
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        console.log(xhr.responseText)
    }
}
xhr.open('get', 'https://www.baidu.com/gethaha')
xhr.send({data: 'haha'})

闭包

function fn(){
    let _a = 22
    return function(){
        return _a
    }
}
let a = fn()
a() // 可访问到内部变量_a

防抖 节流

// 防抖, 时间内触发, 取消定时后-重新计时
function debounce(fn, waitTime) {
  let timer;
  return function () {
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
    timer = setTimeout(fn, waitTime);
  };
}
// 节流 水龙头滴水,时间结束后-再计时
function throttle(fn, waitTime) {
  let timer;
  return function () {
    if (!timer) {
      fn(); // 立即调用
      timer = setTimeout(() => {
        timer = null;
        fn();
      }, waitTime);
    }
  };
}
window.addEventListener(
  "scroll",
  debounce(() => { // 连续触发场景,debounce 最终一次, throttle 1秒一次
    console.log("11");
  }, 1000)
);

promise

status pendding fulfilled rejected
execute(resolve, reject) 执行函数
then(onResolved, onRejected)
异步 then 先收集回调函数,resolve种遍历执行回调函数(可多个then)

function _Promise(execute){
    this.status = 'pendding'
    this.value = null
    this.reason = null
    this.resolveCallbackArr = []
    this.rejectCallbackArr = []

    const resolve = (value) => {
        if(this.status == 'pendding'){
            this.value = value
            this.status = "fulfilled"
            this.resolveCallbackArr.forEach( fn => fn())
        }

    }
    const reject = (reason) => {
        if(this.status == 'pendding'){
            this.reason = reason
            this.status = 'rejected' 
            this.rejectCallbackArr.forEach( fn => fn())
        }
    }

    execute(resolve, reject)

    this.then = function(onFulfilled, onRejected){
        if(this.status == "fulfilled"){
            onFulfilled(this.value)
        }
        if(this.status == "rejected"){
            onRejected(this.reason)
        }
        if(this.status == 'pendding'){
            this.resolveCallbackArr.push(() => {
                onFulfilled(this.value)
            })
            this.rejectCallbackArr.push(() => {
                onRejected(this.reason)
            })
        }
    }
}

let test = new _Promise(function(resolve,reject){
    setTimeout(() => {
        resolve({code: "000000"})
    }, 1000)
})
test.then((data)=>{
    console.log(data)
})

深拷贝

assign 浅拷贝

JSON.parse(JSON.stringify(data))

递归

柯里化

js类继承

js数据类型 8种

String Number Boolean Null Undefined Symbol Bigint Object

array方法

slice(s,e) start~end shift() 首为删 splice(0,2,'3') 0开始删2个,加一个'3' concat() 连接多个 flat(Infinity) 拍平

string方法

slice(s,e) e可为负数 substring() ,自动交换小到大,无负数 substr(s, l)