Maison  >  Article  >  interface Web  >  Où JavaScript pointe-t-il ?

Où JavaScript pointe-t-il ?

青灯夜游
青灯夜游original
2021-06-15 16:27:353807parcourir

Cela pointe vers : 1. Fonction ordinaire ou en tant qu'attribut d'objet, pointant vers l'objet window ; 2. Dans la liaison d'événement, pointant vers l'élément de l'événement lié ; 3. Dans le constructeur, pointant vers le instance de la classe ; 4. Flèche Dans la fonction, il pointe vers son contexte parent le plus proche ; 5. Dans call/apply/bind, il pointe vers le premier paramètre transmis.

Où JavaScript pointe-t-il ?

L'environnement d'exploitation de ce tutoriel : système windows7, javascript version 1.8.5, ordinateur Dell G3

JavaScriptLe this le pointeur est divisé en Les situations suivantes :

  • Fonction ordinaire ou en tant que propriété d'objet
  • Liaison d'événement
  • Constructeur
  • Fonction flèche
  • call/apply/bindSpécifiez

Présentons-les une par une

Fonctions ordinaires ou comme attributs d'objet

thisDépend Y a-t-il un « point » devant l'exécution de la méthode ? S'il y a un « point », celui qui se trouve devant le « point » est this S'il n'y a pas de point, this pointe vers window<.>

const fn = function () {
  console.log(this);
};

const obj = { name: &#39;OBJ&#39;, fn };

fn();

obj.fn();

const fn1 = obj.fn;
fn1();

réponse :

1. window
2. {name: &#39;OBJ&#39;, fn: function() {console.log(this)}} // obj
3. window

peut voir que lorsqu'une fonction est appelée en tant qu'attribut d'un objet, son

pointe vers l'objet qui appelle la fonction, sinon son this pointe vers la liaison d'événement thiswindow

Lors de la liaison d'événement, le

dans la fonction de liaison d'événement est l'élément permettant de lier l'événement : this

// 假设页面中有id为button的button元素
// var x = 100;
window.x = 100;
const fn = function () {
  console.log(this.x);
};
const obj = { x: 200, fn };
const $button = document.getElementById(&#39;button&#39;);
$button.x = 300;

obj.fn();
const fn1 = obj.fn;
fn1();

$button.addEventListener(&#39;click&#39;, fn);
$button.addEventListener(&#39;mouseenter&#39;, obj.fn);

$button.addEventListener(&#39;mouseleave&#39;, function () {obj.fn();});

réponse :

1. 200
2. 100
3. 点击button时:300
4. 鼠标移入button时:300
5. 鼠标移出时:200

Mais il est à noter qu'ici lorsque l'utilisateur clique, le navigateur nous aide à pointer le

de l'événement de clic vers l'élément this lié ​​à l'événement. Si l'événement correspondant est déclenché via le code, nous pouvons spécifier son constructeur DOMcall/apply/bind

$button.click.call() // this为window,打印结果为100
this

(

) new Fn via

(

) est exécuté. Le new Fn dans la fonction est une instance de la classe actuelle. C'est ce que le mot-clé this nous aide à faire : new

var x = 100;
const Fn = function () {
  this.x = 200;
  console.log(this.x);
};

const fn = new Fn();

answer:

1. 200

Fonction flèche

La fonction flèche n'a pas son propre

, et le this utilisé est la thisthis

const fn = function () {
  console.log(this);
  setTimeout(() => {
    console.log(this);
  }, 1000);
  setTimeout(function () {
    console.log(this);
  });
};

const obj = { x: 100, fn };

obj.fn();

réponse :

1. {x:100, fn: function() {...}} // obj
2. window
3. {x:100, fn: function() {...}} // obj

change call/apply/bind pour pointer vers this

pour

Le premier paramètre transmis est le call/apply/bind de la fonction : this

var x = 100;
const obj = { x: 200, y: 200 };
const fn = function () {
  console.log(this.x);
};

fn();
fn.call(obj);
fn.apply(obj);

const fixedThisFn = fn.bind(obj);
fixedThisFn();

réponse :

1. 100
2. 200
3. 200
4. 200

  • Lors de l'exécution, le premier paramètre est pointé par call, et les paramètres suivants sont les paramètres de thisexécutionfn
  • Lors de l'exécution , le premier paramètre est pointé par apply, et les paramètres suivants sont un tableau composé de paramètres lors de l'exécution de this. Chaque élément du tableau correspondra à chaque paramètre de fnfn.
  • est exécuté, le premier paramètre est passé à l'avance et pointé par
  • , et les paramètres suivants sont les paramètres passés à l'avance avant d'appeler réellement bind La valeur de retour est une fonction this, fn fixedThisFn sera appelé en interne et précisera que son fixedThisFn pointe vers fnthis
  • Afin d'avoir une compréhension plus approfondie de la façon dont
change le point de

dans le. fonction, simulons et implémentons ces trois fonctions séparément call/apply/bindthis

Implémentation du code sourcecall/apply/bindD'après l'introduction précédente, nous savons : quand une fonction est appelée comme. un attribut d'objet,

pointe vers l'objet qui appelle la fonction

const obj = { x: 100, fn () {console.log(this);} };
obj.fn(); // {x: 100, fn: function() {...}} => obj
thisEn utilisant la fonctionnalité de

, nous pouvons utiliser la fonction exécutée comme attribut du premier paramètre

de JavaScript , puis appelez la fonction correspondant à l'attribut via call/apply, le context de la fonction pointe alors vers contextthiscontext

La simulation du code source est la suivante :

Function.prototype.myOwnCall = function (context, ...args) {
  const uniqueKey = new Date().getTime();
  // this为调用call方法的函数
  context[uniqueKey] = this;
  // 作为对象的方法被对象调用,this指向该对象context
  const result = context[uniqueKey](...args);
  delete context[uniqueKey];
  return result;
};
À ce stade, certains amis ont peut-être découvert que si call entrant

Et si ce n'était pas un objet ?

call/applyRegardons d'abord la context description du premier paramètre de la méthode

:

mdn Syntaxe : call

*
function.call(thisArg, arg1, arg2, ...) Facultatif . La valeur
utilisée lorsque la fonction thisArg est exécutée. Notez que
peut ne pas être la valeur réelle vue par cette méthode : si cette fonction est en mode non strict, function sera automatiquement remplacé lors de la spécification de this ou this pour pointer vers l'objet global, et la valeur d'origine sera Wrapping nullundefinedEnsuite, nous traitons le premier paramètre de la méthode
comme suit :
function translateToObject (context) {
  // 可以通过 == 进行判断 context == null
  // null == undefined  => 2个等号是成立的
  // null,undefined => window
  if (typeof context === &#39;undefined&#39; || context === null) {
    context = window;
  } else if (typeof context === &#39;number&#39;) { // 原始值转换为包装对象
    context = new Number(context);
  } else if (typeof context === &#39;string&#39;) {
    context = new String(context);
  } else if (typeof context === &#39;boolean&#39;) {
    context = new Boolean(context);
  }
  return context;
}

Appelez la fonction dans la méthode myOwnCall :

Function.prototype.myOwnCall = function (context, ...args) {
  context = translateToObject(context);
  const uniqueKey = new Date().getTime();
  // this为调用call方法的函数
  context[uniqueKey] = this;
  // 作为对象的方法被对象调用,this指向该对象context
  const result = context[uniqueKey](...args);
  delete context[uniqueKey];
  return result;
};

est fondamentalement la même que celle de myOwnCall, sauf que le deuxième paramètre est un tableau :

Function.prototype.myOwnBind = function (context, paramsArray) {
  context = translateToObject(context);
  const uniqueKey = new Date().getTime();
  // this为调用call方法的函数
  context[uniqueKey] = this;
  // 作为对象的方法被对象调用,this指向该对象context
  const result = context[uniqueKey](...paramsArray);
  delete context[uniqueKey];
  return result;
};

相比于call/applybind函数并没有立即执行函数,而是预先传入函数执行时的this和参数,并且返回一个函数,在返回的函数中执行调用bind函数并将预先传入的this和参数传入

bind的源码模拟:

Function.prototype.myOwnBind = function (context, ...outerArgs) {
  const fn = this;
  return function (...innerArgs) {
    return fn.call(context, ...outerArgs, ...innerArgs);
  };
};

精简版如下:

Function.prototype.myOwnBind = (context, ...outerArgs) => (...innerArgs) => this.call(context, ...outerArgs, ...innerArgs);
这里并没有实现通过new操作符来执行fn.bind(context)的操作,如果想知道其详细的实现过程,可以看我的这篇文章: JS进阶-手写bind

在深入理解call/apply/bind的实现原理后,我们尝试完成下面的测试:

function fn1 () {console.log(1);}
function fn2 () {console.log(2);}
fn1.call(fn2);

fn1.call.call(fn2);

Function.prototype.call(fn1);
Function.prototype.call.call(fn1);

answer:

1. 1
2. 2
3. 什么都不输出
4. 1

这里我们根据call的源码来进行推导一下Function.prototype.call.call(fn1),其它的执行过程类似:

// 1. 首先会将Function.prototype.call作为一个函数来执行它原型上的call方法
// 所以call方法内部:
//    this => Function.prototype.call
//    context => fn1
// 通过对象的属性来执行方法改变this指向
//    fn1[uniqueKey] = this(Function.prototype.call)
//    fn1[uniqueKey]() // 执行 Function.prototype.call方法,但是this是context
// 2. 在this为fn1的情况下执行Function.prototype.call方法
// 所以call方法内部:
//    this => fn1
//    context => window
// 通过对象的属性来改变this指向
//    window[uniqueKey] = fn1
//    window[uniqueKey]() // 执行fn1(),但是this是window

更多编程相关知识,请访问:编程入门!!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn