首页 > 其他分享 >js进阶手写常见函数

js进阶手写常见函数

时间:2022-10-03 18:31:29浏览次数:83  
标签:24 console 进阶 js base let 手写 fn log

JavaScript进阶的必要性

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

无论是自我提升还是应付面试以下这些手写功能是每一个前端程序员必须掌握的

1. 手写apply、call、bind

  每个Function对象都存在apply()、call()、bind() 方法,其作用都是可以在特定的作用域
  中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。

apply、call、bind 的异同
  1. 三者都可以改变this的指向,第一个参数都是this,如果指向是null或者undefined则指向window
  2.  apply的参数是数组,call是列表,而bind可以多次传入
  3.  apply和call是改变this的指向之后直接运行函数,而bind则是返回绑定之后的函数

apply实现的参考代码
/** * 手写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

apply代码执行效果

image.png

相关js视频讲解:进入学习
call 实现的参考代码
/** * 手写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

call代码执行效果

image.png

bind实现的参考代码
/** * 手写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

bind代码执行效果

image.png

2. 手写new

new关键字执行时做了哪些
1. 创建了一个新对象
2. 将这个新对象与构造函数用原型链链接起来
3. 将构造函数的this指向新的对象,执行构造函数的代码赋值
4. 如果构造函数没有返回一个对象就返回新创建的对象否则返回构造函数返回的对象

手写new参考代码
/*** * 手写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());

代码执行结果参考图

result.png

原型链示意图

lian.webp

3. 手写instanceof

    typeof 可以判断基本数据类型 但是null 返回的也是object 不能识别 引用数据类型
    instanceof 可以准确的判断引用数据类型不可以判断 基本数据类型
    instanceof是用于检测构造函数的prototype是否出现某个实例对象的原型链上

参考代码
/*** 手写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 )

代码执行结果截图

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

4. 手写防抖和节流

    持续的触发某一事件,延迟n秒后执行回调,在未到n秒再次触发,会从新出发倒计时    持续的触发某一时间,延迟n秒后执行回调,在未达到n秒再次出发,不会重新计时

两者的使用场景

防抖可能用于无法预知的用户主动行为,如用户输入内容去服务端动态搜索结果。用户打字的速度等是无法预知的,具有非规律性。

节流可能用于一些非用户主动行为或者可预知的用户主动行为,如用户滑动商品橱窗时发送埋点请求、滑动固定的高度是已知的逻辑,具有规律性。

节流防抖也是闭包的应用

手写防抖代码参考
/*** * 手写防抖 */
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");

手写防抖代码执行结果

image.png

手写节流
/*** * 手写节流 * 这里只需要注意和防抖不同的时 不会清除定时器 */
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. 手动实现ajax

    AJAX 的全称为 Asynchronous JavaScript + XML, 最重要的要属 XHR(XMLHttpRequest)
    XMLHttpRequest通过不刷新页面请求特定URL,获取数据。

实现的必备条件
  1. XMLHttpRequest() 是一个构造函数

  2. XMLHttpRequest.onreadystatechange 状态码变化时触发事件(所有浏览器支持)

  3. XMLHttpRequest.readyState 请求的状态码

image.png

  1. XMLHttpRequest.status 响应状态码 返回标准的HTTP 状态码

image.png

  1. 其他的请求响应参数

    XMLHttpRequest.response 这个是整个响应实体
    XMLHttpRequest.responseText 返回 `DOMString`
    XMLHttpRequest.timeout 超时时间
    XMLHttpRequest.upload 上传进度
    
    
  2. 在看看常用方法 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" );

基于以上API实现 ajax
    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()
            }
        }
    }
}

标签:24,console,进阶,js,base,let,手写,fn,log
From: https://blog.51cto.com/u_15786042/5730427

相关文章

  • js函数式编程讲解
    什么是函数式编程是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简......
  • js函数式编程讲解
    什么是函数式编程是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简......
  • js进阶手写常见函数
    JavaScript进阶的必要性无论是学习react还是vue,它们都是js的应用框架。剥去他们的壳子看到的始终是js,所以作为一个前端大厨必须要熟练掌握好js这个大勺,才能烧出一顿好菜......
  • 深入理解Node.js的进程与子进程
    进程:process模块process模块是nodejs提供给开发者用来和当前进程交互的工具,它的提供了很多实用的API。从文档出发,管中窥豹,进一步认识和学习process模块:如何处理命......
  • Node.js实现大文件断点续传
    前言平常业务需求:上传图片、Excel等,毕竟几M的大小可以很快就上传到服务器。针对于上传视频等大文件几百M或者几G的大小,就需要等待比较长的时间。这就产生了对应的解决方......
  • Node.js实现大文件断点续传
    前言平常业务需求:上传图片、Excel等,毕竟几M的大小可以很快就上传到服务器。针对于上传视频等大文件几百M或者几G的大小,就需要等待比较长的时间。这就产生了对应的解决方......
  • javaScript--5 javascript json字符串转换
      <!DOCTYPEhtml><html><head><title>JavaScript对象转JSON字符串</title></head><body><script>varjsonObj={"userId":"admin",......
  • [RxJS] Create a scroll progress bar
    //beginlessoncodeimport{fromEvent}from'rxjs';import{map}from'rxjs/operators';/**Calculateprogressbasedonscrollposition*/functionca......
  • Mysql-进阶篇
    存储引擎MySQL体系结构:存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表而不是基于库的,所以存储引擎也可以被称为表引擎。默认存储......
  • [RxJS] Execute tasks asynchronously with Async Scheduler
    TheasyncSchedulerletsyouscheduletasksasynchronously,similartoasetTimeout. Allschedulershaveasignatureofwork,delay,state,butprovdingadel......