如何在 JavaScript 中使用call、apply 和 bind函数(下)

629 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

如何在 JavaScript 中使用绑定函数

该函数在调用函数内部bind创建一个具有新值的函数副本。this

这是bind函数的语法:

func.bind(thisObj, arg1, arg2, ..., argN);

在哪里,

  • func是一个需要用不同的this对象调用的函数
  • thisObj是一个对象或一个值,需要用this函数内部的关键字替换func
  • arg1, arg2...argN – 你可以向调用函数传递 1 个或更多参数,类似于call函数。

然后该bind函数返回一个新函数,该函数包含一个新上下文到this调用函数内部的变量:

func(arg1, arg2);

现在func可以稍后使用参数执行此函数。

让我们看一个如何在bind基于类的 React 组件的帮助下使用函数的经典示例:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 1
    };
  }
  handleCode() {
    console.log("HANDLE CODE THIS = ", this.state);
  }
  render() {
    return <button onClick={this.handleCode}>Click Me</button>;
  }
}

考虑上面的 App 组件。它构成以下内容:

  • constructor是一个被称为类并使用new关键字实例化的函数。
  • render是一个执行/渲染 JSX 代码的函数。
  • handleCode是一个记录组件状态的类方法。

如果我们单击该Click Me按钮,则会收到一条错误消息:Cannot read properties of undefined (reading 'state')

你有没有想过为什么会出现这个问题?🤔🤔

你可能期望我们应该能够访问类的状态,因为handleCode它是一个类方法。但这里有一个问题:

  • this里面的handleCode和类的不一样this
  • 在类内部,this是一个具有非静态类方法作为其属性的常规对象。但是this里面handleCode会指不同的上下文。
  • 老实说,this在这种情况下, 的价值取决于从哪里调用函数。如果你看到,handleCode则正在调用onClick事件。
  • 但是在这个阶段,我们将在函数内部获取 presentundefined的上下文。this``handleCode
  • 我们试图调用state未定义值的属性。因此,这会导致上述错误。

this我们可以通过在方法内部提供正确的上下文来解决这个问题handleCode。你可以使用该bind方法执行此操作。

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 1
    };
   this.handleCode = this.handleCode.bind(this); //bind this function
  }
  handleCode() {
    console.log("HANDLE CODE THIS = ", this.state);
  }
  render() {
    return <button onClick={this.handleCode}>Click Me</button>;
  }
}

bind创建一个新函数并将其存储在this具有新属性的对象中handleCodeBind将确保类的this上下文应用于函数this内部的当前handleCode

如何创建自己的map函数

现在我们已经拥有了所有必要的东西,让我们从创建own地图函数开始。让我们首先了解构建own地图功能所需的东西。

这是map函数的语法:

arr.map(func)

在哪里,

  • arr是调用映射的数组。
  • func是需要在数组的每个元素上运行的函数。

函数的基本功能map很简单:

它是一个遍历数组的每个元素并应用作为参数传递的函数的函数。地图的返回类型同样是一个func应用于每个元素的数组。

现在我们了解了需求,因此我们可以继续创建自己的map函数。这是我们的新map函数的代码:

function newMap(func){
  let destArr = [];
  const srcArrLen = this.length;
  for(let i = 0; i < srcArrLen; i++){
    destArr.push(func.call(this, this[i]));
  }

  return destArr;
} 

让我们一点一点的理解上面的函数:

  • 此函数接受一个名为 的参数func。它只不过是一个需要在数组的每个元素上调用的函数。
  • 代码的其他部分很容易解释。我们将重点关注以下行:destArr.push(func.call(this, this[i]));
  • 这一行做了两件事:\
    1. 将更改推送到destArr\
    2. 在方法func的帮助下执行call。这里的call方法(如前几节所述)将使用方法中存在的对象func的新值执行方法。this``func

现在让我们看看我们将如何执行我们的newMap函数。不建议使用以下向现有原始数据类型添加新方法的方法,但为了本文的目的,我们仍然会这样做。

注意: 不要在你的生产代码中遵循以下方法。这可能会损坏现有代码。

Object.defineProperty(Array.prototype, 'newMap', {
  value: newMap
}); 

defineProperty我们在Array.prototype.

一旦完成,我们就可以在数组上执行新的 map 函数了。

const arr = [1,2,3];
const newArr = arr.newMap(item => item + 1);
console.log(newArr);

结论

感谢你的阅读!