Heim  >  Artikel  >  Web-Frontend  >  Alles, was Sie darüber wissen möchten, finden Sie hier

Alles, was Sie darüber wissen möchten, finden Sie hier

阿神
阿神Original
2017-01-23 16:12:061119Durchsuche

Ob im täglichen Einsatz von Javascript oder im Front-End-Interviewprozess, dies hat eine sehr hohe Auftrittsquote. Dies verdeutlicht zweifellos, wie wichtig dies ist. Dies ist jedoch sehr flexibel, weshalb das Verhalten für viele Menschen schwer zu verstehen ist. Dieser Artikel beginnt damit, warum dies notwendig ist, und fasst die sechs Regeln zusammen. Ich hoffe, er kann Ihnen helfen, Ihre Verwirrung zu beseitigen.

Einführung

dies entspricht tatsächlich einem Parameter. Dieser Parameter kann während der Entwicklung manuell übergeben werden, oder es kann sich um JS oder das handeln 3. Eingehend von drei Parteien.
Dieser Parameter zeigt normalerweise auf den „Eigentümer“, wenn die Funktion ausgeführt wird. Durch diesen Mechanismus kann das Funktionsdesign prägnanter und wiederverwendbarer gestaltet werden.

Dies wird gebunden, wenn die Funktion ausgeführt wird. Es gibt insgesamt sechs Bindungsregeln, nämlich:

●Neue Bindung: Wenn das Schlüsselwort new zum Erstellen eines Objekts verwendet wird, wird an dieses gebunden auf dem erstellten Objekt.

●Explizite Bindung: Bei expliziter Bindung mit der Call-, Apply- oder Bind-Methode ist dies der erste Parameter.

●Implizite Bindung: Wenn eine Funktion auf einem Objekt ausgeführt wird, bindet das System diese implizit an das Objekt.

●Standardbindung: Wenn die Funktion unabhängig ausgeführt wird, ist der Standardbindungswert im strikten Modus undefiniert, andernfalls handelt es sich um das globale Objekt.

●Pfeilfunktionsbindung: Bei Verwendung von Pfeilfunktionen ist der Bindungswert von this gleich dem This seiner äußeren gewöhnlichen Funktion (oder dem globalen Objekt selbst).

●System- oder Drittanbieterbindung: Wenn eine Funktion als Parameter an eine vom System oder einem Drittanbieter bereitgestellte Schnittstelle übergeben wird, wird diese in der übergebenen Funktion vom System oder dem Drittanbieter gebunden.

Die Rolle dieses

Dieser Mechanismus bietet eine elegante Möglichkeit, ein Objekt implizit zu übergeben, wodurch das Funktionsdesign prägnanter und besser wiederverwendbar wird.

Betrachten Sie das folgende Beispiel von zwei Schaltflächen, deren Hintergrund beim Klicken rot wird.

function changeBackgroundColor(ele) {
  ele.style.backgroundColor = 'red';
}
btn1.addEventListener('click',function () {
  changeBackgroundColor(btn1);
});
btn2.addEventListener('click',function () {
  changeBackgroundColor(btn2);
});

Hier übergeben wir explizit das angeklickte Element an die Funktion changeBackgroundColor. Tatsächlich können Sie diese Funktion der impliziten Kontextübergabe jedoch nutzen, um das aktuell angeklickte Element direkt in der Funktion abzurufen. Wie folgt:

function changeBackgroundColor() {    this.style.backgroundColor = 'red';
}
btn1.addEventListener('click',changeBackgroundColor);
btn2.addEventListener('click',changeBackgroundColor);

Im ersten Beispiel wird das angeklickte Element durch ele, diesen formalen Parameter, ersetzt. Im zweiten Beispiel wird es durch ein spezielles Schlüsselwort this ersetzt. Dies hat eine ähnliche Funktion wie formale Parameter. Es handelt sich im Wesentlichen um eine Referenz auf ein Objekt. Die Besonderheit besteht darin, dass keine manuelle Wertübertragung erforderlich ist und die Verwendung daher einfacher und bequemer ist.

Sechs Regeln

Im tatsächlichen Gebrauch ist es am verwirrendsten, auf welches Objekt dies hinweist. Dieser Artikel klassifiziert sechs Szenariotypen und fasst sechs verbindliche Regeln hierfür zusammen.

1.neue Bindung

Wenn Sie new zum Erstellen eines Objekts verwenden, bezieht sich dies auf die Klasse zu Was ist?

class Person {
  constructor(name){
    this.name = name;
  }
  getThis(){
    return this
  }
}
const xiaoMing = new Person("小明");
console.log(xiaoMing.getThis() === xiaoMing); // true
console.log(xiaoMing.getThis() === Person); // false
console.log(xiaoMing.name === "小明"); // true

Im obigen Beispiel wird die Person-Klasse mit der ES6-Syntax erstellt. Beim Erstellen eines Objekts mit dem neuen Schlüsselwort wird dieses vom System automatisch an das erstellte Objekt gebunden, nämlich xiaoMing.

Regel 1: Wenn Sie das Schlüsselwort new zum Erstellen eines Objekts verwenden, wird dieses an das erstellte Objekt gebunden.

2. Explizite Bindung


Szenario 2: Verwenden Sie die Methoden call, apply und bind, um diesen Parameter explizit zu binden.

Nehmen Sie call als Beispiel. Der erste Parameter, der an die call-Methode übergeben wird, ist das Objekt, auf das hierdurch verwiesen wird.

function foo() {  console.log( this === obj ); // true
  console.log( this.a === 2 ); // true}const obj = {
  a: 2};
foo.call( obj );

Bei expliziter Übergabe ist das Objekt, auf das dies zeigt, offensichtlich. Dies ist der erste Parameter der Aufruf-, Anwendungs- oder Bindungsmethode.

Regel 2: Bei expliziter Bindung mit der Methode call, apply oder bind ist dies der erste Parameter.

3. Implizite Bindung


Der Unterschied zwischen impliziter Bindung und expliziter Bindung besteht darin, dass die explizite Bindung dem Entwickler überlassen bleibt Geben Sie dies an; wenn die Funktion oder Methode implizit gebunden ist, hat sie einen „Eigentümer“, und dieser „Eigentümer“ bezieht sich auf das Funktions- oder Methodenobjekt, das direkt aufgerufen wird.

Beispiel 1

Schauen wir uns zunächst das einfachste Beispiel an.

function bar() {  console.log( this === obj );
}const obj = {
  foo: function () {    console.log( this === obj );
  },
  bar: bar
};
obj.foo(); // trueobj.bar(); // true


Die Funktion foo wird direkt in das Objekt obj eingehängt, und die Funktionsleiste wird außerhalb definiert und dann an das Objekt obj gehängt. Egal wo die Funktion definiert ist, wenn die Funktion schließlich aufgerufen wird, ist ihr „Eigentümer“ obj. Dies zeigt also auf das Objekt „Eigentümer“, wenn die Funktion aufgerufen wird.

Beispiel 2

Für ein tieferes Verständnis betrachten wir den Fall der Neuzuweisung einer Funktion zu einem neuen Objekt.

function bar() {  console.log( this === obj1 ); // false
  console.log( this === obj2 ); // true}const obj1 = {
  foo: function () {    console.log( this === obj1 ); // false
    console.log( this === obj2 ); // true
  },
  bar: bar
};const obj2 = {
  foo: obj1.foo,
  bar: obj1.bar
};

obj2.foo();
obj2.bar();

In diesem Beispiel werden die foo- und bar-Methoden in obj1 obj2 zugewiesen. Wenn die Funktion aufgerufen wird, ist der „Eigentümer“ obj2, nicht obj1. Das deutet also auf obj2 hin.

Beispiel 3

Objekte können auf mehreren Ebenen verschachtelt werden. Wer ist in diesem Fall der „Eigentümer“ der Funktion?

const obj1 = {
  obj2: {
    foo: function foo() {      console.log( this === obj1 );      // false
      console.log( this === obj1.obj2 ); // true
    }
  }
};

obj1.obj2.foo()

Der direkte Aufrufer in der foo-Methode/-Funktion ist obj2, nicht obj1, sodass der „Eigentümer“ der Funktion auf den nächstgelegenen direkten Aufrufer verweist.

Beispiel 4

如果一个方法/函数,在它的直接对象上调用执行,又同时执行了 call 方法,那么它是属于隐式绑定还是显式绑定呢?

const obj1 = {
  a: 1,
  foo: function () {    console.log(this === obj1); // false
    console.log(this === obj2); // true
    console.log(this.a === 2);  // true
  }
};const obj2 = {
  a: 2};

obj1.foo.call(obj2); // true

由上,可以看出,如果显式绑定存在,它就不可能属于隐式绑定。

规则三:如果函数是挂在对象上执行的,这个时候系统会隐式的将 this 绑定为函数执行时的“拥有者”。

4.默认绑定

前一小段,讨论了函数作为对象的方法执行时的情况。本小段,要讨论的是,函数独立执行的情况。

在函数直接调用的情况下,this 绑定的行为,称之为默认绑定。

例一

为了简单起见,先讨论在浏览器的非严格模式的下绑定行为。

function foo() {  console.log( this === window); // true}
foo();

在上面的例子中,系统将 window 默认地绑定到函数的 this 上。

例二

在这里,先介绍一种我们可能会在代码中见到的显式绑定 null 的写法。

function foo() {  console.log( this == window ); // true}

foo.apply(null);

将例一默认绑定的情况,改为了显式绑定 null 的情况。

在实际开发中,我们可能会用到 apply 方法,并在第一个参数传入 null 值,第二个参数传入数组的方式来传递数组类型的参数。这是一种传统的写法,当然现在可以用 ES6 的写法来代替,但是这不在本文的讨论范围内。

在本例最需要关注的是,this 竟然指向的 window 而不是 null。个人测试的结果是,在函数独立调用时,或者显式调用,传入的值为 null 和 undefined 的情况下,会将 window 默认绑定到 this 上。

在函数多次调用,形成了一个调用栈的情况下,默认绑定的规则也是成立的。

例三

接着,探讨下严格模式下,this 的默认绑定的值。

"use strict";

function foo() {
  console.log( this === undefined );
}

foo();               // true
foo.call(undefined); // true
foo.call(null);      // false

在严格模式下,this 的默认绑定的值为 undefined。

规则四:在函数独立执行的情况下,严格模式 this 的默认绑定值为 undefined,否则默认绑定的值为 window。

5.箭头函数绑定

箭头函数实际上,只是一个语法糖,实际上箭头函数中的 this 实际上是其外层函数(或者 window/global 本身)中的 this。

// ES6
function foo() {
  setTimeout(() => {
    console.log(this === obj); // true
  }, 100);
}

const obj = {
  a : 1
}

foo.call(obj);

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log(_this === obj); // true
  }, 100);
}

var obj = {
  a : 1
}

foo.call(obj);

规则五:使用箭头函数时,this 的绑定值和其外层的普通函数(或者 window/global 本身) this 绑定值相同。

6.系统或第三方绑定

在 JavaScript 中,函数是第一公民,可以将函数以值的方式,传入任何系统或者第三方提供的函数中。现在讨论,最后一种情况。当将函数作为值,传入系统函数或者第三方函数中时,this 究竟是如何绑定的。

我们在文章一开始提到的,两个按钮例子,系统自动将 this 绑定为点击的按钮。

function changeBackgroundColor() {    console.log(this === btn1); // true}

btn1.addEventListener('click',changeBackgroundColor);

接着测试系统提供的 setTimeout 接口在浏览器和 node 中绑定行为。

// 浏览器
setTimeout(function () {
  console.log(this === window); // true
},0)

// node
setTimeout(function () {
  console.log(this === global); // false
  console.log(this); // Timeout
},0)

很神奇的是,setTimeout 在 node 和浏览器中的绑定行为不一致。如果我们将 node 的中的 this 打印出来,会发现它绑定是一个 Timeout 对象。

如果是第三发提供的接口,情况会更加复杂。因为在其内部,会将什么值绑定到传入的函数的 this 上,事先是不知道的,除非查看文档或者源码。

系统或者第三方,在其内部,可能会使用前面的五种规则一种或多种规则,对传入函数的 this 进行绑定。所以,规则六,实际上一条在由前五条规则上衍生出来的规则。

规则六:调用系统或者第三方提供的接口时,传入函数中的 this 是由系统或者第三方绑定的。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:12 JavaScript-TippsNächster Artikel:12 JavaScript-Tipps