首页>>前端>>JavaScript->实用的js方法及手写部分内置方法

实用的js方法及手写部分内置方法

时间:2023-12-01 本站 点击:0

说明

本文主要撰写比较适用、耐用,及常见处理业务的js方法,同时会对部分内置的js方法进行手写,旨在一方面掌握这些提高效率的js方法,另一方面对内置方法的手写剖析,加深大家对方法的封装逻辑。

本文属于长期贴,会在发布的前提下进行不定期更新,为了避免错乱,该文章的目录结构会根据更新点划分。本人会在实际开发中尽量多的学习和掌握新的知识点,并不断完善该文章的内容。

读者如有发现本文在编写过程中有不对的、不恰当的地方,望及时告知,不吝感谢!

一、更新一(2022.05.17)

1.实现数组和对象的forEach

我们平时开发中经常在使用forEach,那么有没有思考过forEach内部是怎么实现的呢?了解真相才能实现真正的自由,现在我们就要剖析一下forEach内部的逻辑。

须知:

内置的forEach只能遍历数组,遍历对象时报错;

手写的方法支持遍历数组和对象;

手写的forEach只是单纯的实现功能方法,并没有挂载原型上;

本方法手写内容思路源于axios源码中,可至utils的工具函数查看。

const _toString = Object.prototype.toString;

//封装判断是否是数组的方法 function isArray(value) { return _toString.call(value) === "[object Array]"; }

//封装forEach function forEach(val, fn) { // (1)null和undefined时,直接返回,不做处理 if (val === null || val === undefined) { return; } // (2)如果不是对象,则转换成数组类型 if (typeof val !== "object") { val = [val]; } // (3)分别处理数组和对象的情况 if (isArray(val)) { for (let i = 0, j = val.length; i < j; i++) { //回调函数内this指向改为null fn.call(null, val[i], i, val); } } else { for (const k in val) { // for in 遍历对象是包括了原型链上的可枚举属性,使用hasOwnProperty只选择实例对象上的可枚举属性 if (val.hasOwnProperty(k)) { //回调函数内this指向改为null fn.call(null, val[k], k, val); } } } }

// 例子: const arr1 = [1, 2, 3, 4, 5]; const arr2 = { id: 1, name: "阿离", age: 18 };

forEach(arr1, (item, index, arr) => { console.log(item, index, arr); }); // 1 0 [ 1, 2, 3, 4, 5 ] // 2 1 [ 1, 2, 3, 4, 5 ] // 3 2 [ 1, 2, 3, 4, 5 ] // 4 3 [ 1, 2, 3, 4, 5 ] // 5 4 [ 1, 2, 3, 4, 5 ]

forEach(arr2, (item, index, arr) => { console.log(item, index, arr); }); // 1 id { id: 1, name: '阿离', age: 18 } // 阿离 name { id: 1, name: '阿离', age: 18 } // 18 age { id: 1, name: '阿离', age: 18 }

#### 2.手写call()方法我们可以使用`call`方法执行某函数,并**显示调用**改变该方法内部`this`的指向。该方法的语法和作用与 `apply()` 方法类似,只有一个区别,就是 `call()` 方法接受的是**一个参数列表**,而 `apply()` 方法接受的是**一个包含多个参数的数组**。`call()`方法详情可至[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call)查阅。```js// 手写callFunction.prototype.alCall = function (thisArg, ...argArray) {  // 1.获取函数  var fn = this;  // 2.处理this  thisArg = thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;  // 3.处理函数  thisArg.fn = fn;  // 4.执行函数  var result = thisArg.fn(...argArray);  delete thisArg.fn;  return result;};function sum(num1, num2) {  return num1 + num2;}var result = sum.alCall({ name: "aaa" }, 20, 40); // 60var result = sum.alCall("西西", 1, 40); // 41

3.手写apply()方法

上面有提到apply()call()都能改变函数this指向,并且说明了两者的区别,此处不再赘述。apply()方法详情可至MDN查阅。

// 1.手写apply//注意apply参数就是以数组或者类数组存在,因此不能用扩展运算符展开argArrayFunction.prototype.alApply = function (thisArg, argArray) {  // 2.获取执行函数  var fn = this;  // 3.处理传递的指定thisArg  thisArg = thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;  // 4.把执行的函数的this隐式指向指定的参数  thisArg.fn = fn;  // 5.处理参数  argArray = argArray ? argArray : [];  // 6.执行函数(实际执行的函数接收的参数需要使用扩展运算符展开)  var result = thisArg.fn(...argArray);  // 7.移除this上的fn属性  delete thisArg.fn;  // 8.返回值  return result;};// 执行函数function fn() {  console.log(this);}function sum(num1, num2) {  console.log(this);  return num1 + num2;}fn.alApply({ name: "ali" }); // this => { name: 'ali'}var result = sum.alApply("aaa", [20, 30]); // this => [String: 'aaa']console.log(result); // 50

4.手写bind()方法

bind()方法同样可以改变函数的this指向,但是并不会像call()apply()一样会直接执行函数。bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。bind()方法详情可至MDN查阅。

//手写bindFunction.prototype.alBind = function (thisArg, ...argArray) {  // 1.获取函数  var fn = this;  // 2.获取this  thisArg = thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;  // 3.返回函数(bind方法返回的是新函数)  return function (...arg) {    // 4.处理函数this    thisArg.fn = fn;    // 5.获取最终参数(包括执行bind时接收的其他参数,即执行新函数接收的参数)    var finalArgs = [...argArray, ...arg];    var result = thisArg.fn(...finalArgs);    delete thisArg.fn;    return result;  };};function sum(num1, num2, num3, num4) {  console.log(this);  return num1 + num2;}var foo = sum.alBind({ name: "xixi" }); var result1 = foo(10, 20, 30, 40); // this => { name: "xixi" }, result => 30var result2 = foo( 30, 40); // this => { name: "xixi" }, result => 70
原文:https://juejin.cn/post/7098530669122289701


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/JavaScript/6404.html