Parlez également de la façon d'implémenter la liaison, l'application, l'appel

Parlez également de la façon d'implémenter la liaison, l'application, l'appel

Nous savons que la liaison, l'application et l'appel de JavaScript sont trois méthodes très importantes. bind peut renvoyer des wrappers de fonction avec this et des paramètres fixes; apply et call peuvent modifier le pointage de la fonction membre this. L'implémentation de la liaison, de l'application et de l'appel est un problème à haute fréquence dans les entretiens frontaux, et nous permet également de mieux comprendre et maîtriser les connaissances pertinentes des fonctions JavaScript. Cet article vous expliquera comment implémenter bind, appliquer et appeler par vous-même.

Préface

Cet article donne d'abord la définition de classe et la définition d'instance suivantes.

// Person类,每个人有姓名,有打印姓名的方法
function Person(_name) {
  this.name = _name
  this.sayMyName = function (postfix) {
    console.log(this.name + postfix)
  }
}
// 两个实例
let alex = new Person('Alex')
let bob = new Person('Bob')

Implémenter la liaison

Pourra peut-être examiner d'abord l'utilisation de la liaison:

let sayBobName = alex.sayMyName.bind(bob, '?')
sayBobName() // Bob?

Visible:

  • bind retourne une copie de la fonction (fonction encapsulée), fixe ce paramètre et les paramètres réels. cela ne pointe pas vers l'appelant
  • bind est une méthode sur le prototype de fonction

Connaissant ces deux points, il n'est pas difficile d'écrire une implémentation:

function MyBind(context, ...args) {
  let that = this // this是调用者,也就是被包装的函数(alex.sayMyName)
  return function () { // 返回一个包装过的函数
    return that.call(context, ...args) // 其返回值是以context为this的执行结果
  }
}
Function.prototype.bind = MyBind

Mettre en œuvre l'appel

Nous avons utilisé call dans le processus d'implémentation de bind. Alors, comment mettre en œuvre un appel? Peut souhaiter revoir l'utilisation de l'appel:

alex.sayMyName.call(bob, '!') // Bob!

Visible:

  • lier modifier cela de la fonction actuelle afin qu'elle ne pointe pas vers l'appelant
  • Les arguments sont passés dans ... reste

Connaissant ces deux points, il n'est pas difficile d'écrire une implémentation:

function MyCall(context, ...args) {
  context._fn = this // this是调用者,也就是当前函数。此步给context绑上该函数
  // 有个细节问题是,可能需要备份原先的context._fn,避免意外覆盖
  let ret = context._fn(..args) // 模仿context自己调用_fn
  delete context._fn // 移除绑的函数
  return ret
}
Function.prototype.call = MyCall

Mettre en œuvre appliquer

Les fonctions d'application et d'appel sont les mêmes, et les méthodes d'utilisation sont fondamentalement similaires. La seule différence est:

  • Les paramètres sont transmis sous forme de tableau

Par conséquent, vous pouvez écrire pour obtenir:

function MyApply(context, args) {
  return MyCall(context, ...args)
}
Function.prototype.apply = MyApply

Triangle stable

D'après ce qui précède, nous pouvons voir que l'application et l'appel peuvent atteindre la liaison, alors comment utiliser la liaison pour implémenter l'application et l'appel, afin de créer cette relation de triangle de fer?

    bind
  /      \      两两都可互相实现的三角形!
call -- apply

C'est simple! Exécutez simplement cette copie de fonction immédiatement!

function AnotherMyCall(context, ...args) {
  return (this.bind(context, ...args))()
}

Je suppose que tu aimes

Origine www.cnblogs.com/zxuuu/p/12735316.html
conseillé
Classement