Fonction d'écriture manuscrite avancée JavaScript

Le besoin de JavaScript avancé

无论是学习react还是vue,它们都是js的应用框架。剥去他们的壳子看到的始终是js,所以作为一个前端大厨必须要熟练掌握好js这个大勺,才能烧出一顿好菜

Qu'il s'agisse d'auto-amélioration ou de faire face à des entretiens, les fonctions manuscrites suivantes doivent être maîtrisées par chaque programmeur frontal

1. Manuscrit appliquer, appeler, lier

  每个Function对象都存在apply()、call()、bind() 方法,其作用都是可以在特定的作用域
  中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。
复制代码
Similitudes et différences entre appliquer, appeler et lier
  1. 三者都可以改变this的指向,第一个参数都是this,如果指向是null或者undefined则指向window
  2.  apply的参数是数组,call是列表,而bind可以多次传入
  3.  apply和call是改变this的指向之后直接运行函数,而bind则是返回绑定之后的函数
复制代码
Code de référence pour l'implémentation de l'application
/**
 * 手写apply
 */
window.name='gy' // 全局变量 
let obj={
  name:'ckx'
}

var func=function(b,c){
  console.log(`this=`, this)
  console.log(this.name,b,c)
  return 1
}

func('24','hz')   //  gy 24 hz

func.apply(obj,['24','hz']) // ckx 24 hz

let newObj={
  name:'xmx',
  age:24
}
Function.prototype.myApply=function(base,args){
  // 1. 如果指向是null 或者undefined 则指向window
  base=base || window
  // 2. 根据this是谁调用就指向谁的原理,将this指向的函数 赋值给base对象的一个属性
  base.fn=this
  // 3.执行函数,调用base.fn时,fn中的函数指向 base对象
  let result=base.fn(...args)
  // 4. 删除base的fn属性
  delete base.fn
  // 5. 返回result 结果
  return  result
}

func.myApply(newObj,['55','yw']) // xmx 55 yw
复制代码
appliquer l'effet d'exécution du code

image.png

Code de référence pour la mise en œuvre de l'appel
/**
 * 手写call
 */
window.name='gy' // 全局变量 
let obj={
  name:'ckx'
}

var func=function(b,c){
  console.log(`this=`, this)
  console.log(this.name,b,c)
  return 1
}

func('24','hz')   //  gy 24 hz

func.call(obj,'24','hz') // ckx 24 hz

let newObj={
  name:'xmx',
  age:24
}
// call 和apply需要注意参数的格式即可
Function.prototype.myCall=function(base,...args){
  // 1. 如果指向是null 或者undefined 则指向window
  base=base || window
  // 2. 根据this是谁调用就指向谁的原理,将this指向的函数 赋值给base对象的一个属性
  base.fn=this
  // 3.执行函数,调用base.fn时,fn中的函数指向 base对象
  let result=base.fn(...args)
  // 4. 删除base的fn属性
  delete base.fn
  // 5. 返回result 结果
  return  result
}

func.myCall(newObj,'55','yw') // xmx 55 yw
复制代码
Effet d'exécution du code d'appel

image.png

Code de référence pour l'implémentation de la liaison
/**
 * 手写bind
 */
window.name = "gy"; // 全局变量
let obj = {
  name: "ckx",
};

var func = function (b, c,d) {
  console.log(`this=`, this);
  console.log(this.name, b, c,d);
  return 1;
};

func("24", "hz",26); //  gy 24 hz 26

let funcRes = func.bind(obj, "24", "hz");
funcRes(24);  // ckx 24 hz 24

let newObj = {
  name: "xmx",
  age: 24,
};
// 注意bind 返回的时绑定的函数以及可以多次传递参数
Function.prototype.myBind = function (base, ...args1) {
  return (...args2) => {
    // 1. 如果指向是null 或者undefined 则指向window
    base = base || window;
    // 2. 根据this是谁调用就指向谁的原理,将this指向的函数 赋值给base对象的一个属性
    base.fn = this;
    // 3.执行函数,调用base.fn时,fn中的函数指向 base对象
    let result = base.fn(...args1,...args2);
    // 4. 删除base的fn属性
    delete base.fn;
    // 5. 返回result 结果
    return result;
  };
};
let myfuncRes=func.myBind(newObj, "55", "yw")
myfuncRes(24) // xmx 55 yw 24
复制代码
Lier l'effet d'exécution du code

image.png

2. Manuscrit nouveau

Que fait le nouveau mot-clé lorsqu'il s'exécute ?
1. 创建了一个新对象
2. 将这个新对象与构造函数用原型链链接起来
3. 将构造函数的this指向新的对象,执行构造函数的代码赋值
4. 如果构造函数没有返回一个对象就返回新创建的对象否则返回构造函数返回的对象
复制代码
Nouveau code de référence manuscrit
/***
 * 手写new关键字执行
 */

function Person(name,age) {
  this.name = name;
}
Person.prototype.getName = function () {
  return this.name;
};
let a = new Person('gy');
console.log(a);
console.log(a.getName());


const myNew = (Func, ...args) => {
  let newObj = {};
  newObj.__proto__=Func.prototype
  let result=Func.apply(newObj,args)
  return  typeof result == Object ? result: newObj
};
let b = myNew(Person,'gy1')
console.log(b);
console.log(b.getName());
复制代码
Diagramme de référence des résultats d'exécution du code

résultat.png

Schéma de principe de la chaîne prototype

lian.webp

3. Exemple manuscrit de

    typeof 可以判断基本数据类型 但是null 返回的也是object 不能识别 引用数据类型
    instanceof 可以准确的判断引用数据类型不可以判断 基本数据类型
    instanceof是用于检测构造函数的prototype是否出现某个实例对象的原型链上
复制代码
Code de référence
/**
* 手写instanceof
*/
let obj= { label:'gy' }
let arr= ['hello']

let result = obj instanceof Object
let result1 = arr instanceof Array
let result2 = arr instanceof Object
let result3 = obj instanceof Array

console.log('result=',result )
console.log('result1=',result1 )
console.log('result2=',result2 )
console.log('result3=',result3 )

const myInstanceof = (left,right)=>{
    if(typeof left != 'object' || left == null ) return false
    let proto= Object.getPrototypeOf(left)
    while(true){
        if(proto==null) return false
        if(proto==right.prototype) return true
        proto=Object.getPrototypeOf(proto)
    }
}

const myResult= myInstanceof(obj,Object)
const myResult1= myInstanceof(arr,Array)
const myResult2= myInstanceof(arr,Object)
const myResult3= myInstanceof(obj,Array)

console.log('myRsult=',myResult )
console.log('myResult1=',myResult1 )
console.log('myResult2=',myResult2 )
console.log('myResult3=',myResult3 )
复制代码
Capture d'écran du résultat de l'exécution du code

image.png 根据上面的代码打印结果 需要注意的是:万物皆对象,包括数组,如果存在一个变量(arrOrObj)可能为array或者object 如果使用instanceof 去判断,一定需要先判断是否为数组先,否则 arrOrObj instanceof Object 一定为true 就无法区分 array和object

4. Stabilisation et limitation de l'écriture manuscrite

    持续的触发某一事件,延迟n秒后执行回调,在未到n秒再次触发,会从新出发倒计时
    持续的触发某一时间,延迟n秒后执行回调,在未达到n秒再次出发,不会重新计时
复制代码
Utilisez des scénarios pour les deux

防抖Peut être utilisé pour le comportement actif imprévisible de l'utilisateur, tel que le contenu d'entrée de l'utilisateur dans les résultats de recherche dynamiques du serveur. La vitesse de frappe de l'utilisateur est imprévisible et irrégulière.

节流Il peut être utilisé pour certains comportements actifs non-utilisateurs ou comportements actifs prévisibles de l'utilisateur, tels que l'envoi d'une demande de points enterrés lorsque l'utilisateur fait glisser la fenêtre du produit, et la hauteur fixe coulissante est une logique connue et a une régularité.

节流et 防抖est aussi une application de fermetures

Référence manuscrite du code anti-tremblement
/***
 * 手写防抖
 */
const debounce = (func, delay) => {
  let timer = null;
  return function (...args) {
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
    timer = setTimeout(() => {
      func(args);
    }, delay);
  };
};
const getfn = (data) => {
  console.log(data);
};
debounce(getfn, 2000)("gy");
复制代码
Résultat d'exécution du code anti-tremblement manuscrit

image.png

limitation manuscrite
/***
 * 手写节流
 * 这里只需要注意和防抖不同的时 不会清除定时器
 */
const throttle = (func, delay) => {
  let flag = false;
  return function (...args) {
    if (flag)  return
    flag=true
    setTimeout(() => {
      func(args);
      flag=false
    }, delay);
  };
};
const getfn = (data) => {
  console.log(data);
};
throttle(getfn, 2000)("gy");
复制代码

5. Implémenter manuellement ajax

    AJAX 的全称为 Asynchronous JavaScript + XML, 最重要的要属 XHR(XMLHttpRequest)
    XMLHttpRequest通过不刷新页面请求特定URL,获取数据。
复制代码
Conditions préalables à la mise en œuvre
  1. XMLHttpRequest() est un constructeur

  2. XMLHttpRequest.onreadystatechangeDéclencher un événement lorsque le code d'état change (pris en charge par tous les navigateurs)

  3. XMLHttpRequest.readyState le code d'état de la demande

image.png

  1. XMLHttpRequest.status Le code d'état de la réponse renvoie le code d'état HTTP standard

image.png

  1. Autres paramètres de réponse à la demande

     XMLHttpRequest.response 这个是整个响应实体
     XMLHttpRequest.responseText 返回 `DOMString`
     XMLHttpRequest.timeout 超时时间
     XMLHttpRequest.upload 上传进度
    复制代码
  2. Examen des méthodes courantes

open()

 // method/url 是必须的
 xhr.open(method, url, async, user, password);
复制代码

send()

// body 可选默认为null
// 可以是 Blob, BufferSource (en-US), FormData, 
// URLSearchParams, 或者 USVString 对象.
XMLHttpRequest.send(body);
复制代码

setRequestHeader()

XMLHttpRequest.setRequestHeader(header, value);
// 例如
XMLHttpRequest.setRequestHeader ("content-type", "application/x-www-form-urlencoded" );
复制代码
Implémenter ajax basé sur l'API ci-dessus
    1.  构造一个请求 XMLHttpRequest
    2.  初始化一个请求 open
    3.  监听请求 onreadystatechange
    4.  发送该请求 send
复制代码
/**
* 手写一个ajax
*/
const myAjax =(url,methods,header,success,error)=>{
    // 创建一个请求
    let request=new XMLHttpRequest()
    // 设置请求头
    for (const key in header) {
        request.setRequestHeader(key,header[key])
    }
    // 初始化请求
    request.open(methods,url)
    // 发送请求
    request.send()
    // 监听请求 onreadystatechange
    request.onreadystatechange =function(){
        if(request.readyState==4){
            if(request.status==200){
                success(request.response)
            }else {
                error()
            }
        }
    }
}
复制代码

Résumer

    欢迎提出更好的思路以及其他必备手写功能
    
复制代码

Je suppose que tu aimes

Origine juejin.im/post/7086717540029693966
conseillé
Classement