【JS手写系列】手写实现ajax、new、instanceof

321 阅读3分钟

靡不有初,鲜克有终

不积跬步无以至千里

1、ajax

  • 具体实现
const ajax = {
    get (url, callBack) {
        const xhr = new XMLHttpRequest()
        xhr.open('GET', url, true)
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                callBack(JSON.parse(xhr.response))
            }
        }
        xhr.send()
    },
    post (url, data, callBack) {
        const xhr = new XMLHttpRequest()
        xhr.open('POST', url, true)
        // 注意:在post请求中,必须在open和send之间添加HTTP请求头
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                callBack(xhr.responeText)
            }
        }
        xhr.send(data)
    }
}
​
const baseUrl = 'https://www.fastmock.site/mock/c65ee7ef23bb5e125732b853ebef16b6/SquirrelSpace'
​
ajax.get(
    baseUrl + '/login',
    (res) => {
        console.log('最后的结果:', res);
    }
)
​
  • readyState

    • 定义

      • 指运行ajax所经历过的几种状态,无论访问是否成功都将响应的步骤,可以理解成为ajax运行步骤。如:正在发送,正在响应等,由ajax对象与服务器交互时所得
    • 运行的各个过程的值和含义 0 - (未初始化),还没有调用send()方法,在定义后自动具有的状态值 1 - (载入),已调用send()方法,正在发送请求 2 - (载入完成),send()方法执行完成 3 - (交互),正在解析响应内容 4 - (完成),响应内容解析完成,可以在客户端调用了

Note: 市面上已经有很多的成熟框架,比如axios、fetch、jQuery等,使用方式大同小异,这里只进行了简易的手写。

2、new

MDN 上 new 关键字的描述

  • 思路
    • new关键字会进行如下的操作:
      • 创建一个空的简单对象,因为new操作符会返回一个对象
      • 将新对象的内部属性__proto__指向构造函数Func的原型
      • 将步骤1新创建的空对象作为 this 的上下文
      • 如果该函数没有返回对象,则返回this,也就是newObj
  • 代码

    // new: 运算符创建一个  用户定义的对象类型的实例或具有构造函数的内置对象的  实例function myNew (Func, ...args) {
        // 创建一个对象,因为new操作符会返回一个对象
        let newObj = {}
    ​
        // 将对象与构造函数原型链接起来
        // 将新对象的内部属性__proto__指向构造函数的原型,这样新对象就可以访问原型中的属性和方法
        newObj.__proto__ = Func.prototype
        // Object.setPrototypeOf(newObj, Func.prototype) 
    ​
        // 将构造函数中的this指向这个newObj对象,并传递参数
        let result = Func.apply(newObj, args)
        // let result = Func.call(newObj, ...args)
    ​
    ​
        console.log('result', result);
        console.log('newObj', newObj);
      
        // 如果该函数没有返回对象,则返回newObj
        return result instanceof Object ? result : newObj
        // return typeof result === "object" ? result : newObj;
    }
    

    a、未返回对象

    function tesFunc (...args) {
        console.log('打印一下...', ...args);
        // return { testFeild: 'testFeild' }
    }
    ​
    ​
    // 原生new
    var resultA = new tesFunc('A', 'A');
    ​
    // 手写new
    var resultB = myNew(tesFunc, 'B', 'B');
    ​
    console.log('resultA', resultA);
    console.log('resultB', resultB);
    

    结果:

    图片.png

    b、返回对象

    function tesFunc (...args) {
        console.log('打印一下...', ...args);
        return { testFeild: 'testFeild' }
    }
    ​
    ​
    // 原生new
    var resultA = new tesFunc('A', 'A');
    ​
    // 手写new
    var resultB = myNew(tesFunc, 'B', 'B');
    ​
    console.log('resultA', resultA);
    console.log('resultB', resultB);
    

    结果:

    图片.png

  • 原型链图解

    图片.png

3、instanceof

  • 思路

    • 首先获取对象的原型
    • 然后获得类型的原型
    • 然后一直循环判断对象的原型是否等于类型的原型,直到对象原型为 null,因为原型链最终为null
  • 代码

    function myInstanceof (left, right) {
        let proto = left.__proto__;
        let prototype = right.prototype
    ​
        while (true) {
            if (proto === null) return false
            if (proto === prototype) return true
            proto = proto.__proto__;
        }
    }
    ​
    ​
    // 原生API用法
    console.log({} instanceof Object) // true// 手写instanceof
    console.log(myInstanceof({}, Object)); // true
    
  • 总结

    • instanceof的原理其实就是一个查找原型链的过程
    • 用来检测一个对象在其原型链中是否存在一个构造函数的 prototype 属性

4、最后

这篇文章仅仅用于记录手写代码。

优质参考链接👇:

手写源码系列

由浅入深,66条JavaScript面试知识点

面试题:手写ajax

Ajax详解(手写jq和axios部分实现)

instanceof的实现原理浅析及手写instanceof的实现