Heim > Web-Frontend > js-Tutorial > Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

coldplay.xixi
Freigeben: 2021-03-16 09:56:11
nach vorne
2578 Leute haben es durchsucht

Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

Inhalt

  • Vorwort + Fragen
  • 1. Der Sinn davon
  • 2. Anrufen und bewerben
  • 3. Anruf simulieren
  • 4. binden
  • 5. Ende

Vorwort + Gedankenfragen

Ich erinnere mich, dass ich bei der Suche nach einem Praktikum immer einen Satz in meinen Lebenslauf eingefügt habe – mit JS vertraut, wie diesen, anrufen, bewerben usw.

Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

(kostenlose Lernempfehlung: Javascript-Video-Tutorial)

Jedes Mal, wenn ich meinen Lebenslauf einreiche, werde ich die folgenden Schritte durchgehen

  • Fragen Sie Du Niang vor dem Vorstellungsgespräch – welche Arten dieser Darstellung können unterteilt werden in ~, anrufen und bewerben Was ist der Unterschied? Mein Selbstvertrauen ist von 0 % auf 50 % gestiegen.
  • Während des Interviews wirft der Interviewer wahllos ein paar Fragen und ich kann „sichere“ Antworten geben, aber die Ergebnisse sind immer unbefriedigend ...
  • Nach dem Interview Ich werde mich schämen. Streichen Sie diesen Punkt aus Ihrem Lebenslauf. Und als ich später meinen Lebenslauf eingereicht habe, habe ich diesen Punkt noch einmal hinzugefügt ...

Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

Denkfragen

Die folgenden Fragen sind beliebte Fragen, die ich im Internet gesucht habe. Wenn die Experten sie leicht beantworten können. Wenn Sie eine haben Klare Idee, ihr könnt ihr genauso gut einen Daumen hoch geben (schließlich verbraucht es eine Menge Gehirnzellen). Es wäre sogar noch besser, wenn ihr mir in den Kommentaren ein paar Hinweise geben könntet! ! !

Füllen Sie die Lücken aus:

  • Durch die Ausführung der Funktion [ ] wird eine neue Funktion erstellt, die mit der aufgerufenen Funktion übereinstimmt aufgerufen, dieser Wert zeigt auf den ersten Parameter. 【 】函数会创建一个新函数,新函数与被调函数具有相同的函数体,当目标函数被调用时 this 值指向第一个参数。

问答题:

  • 请你谈一下改变函数内部this指针的指向函数有哪几种,他们的区别是什么?
  • this的指向可以分为哪几种?

代码分析题:

var name = 'window'var person1 = {
  name: 'person1',
  show1: function () {
    console.log(this.name)
  },
  show2: () => console.log(this.name),
  show3: function () {
    return function () {
      console.log(this.name)
    }
  },
  show4: function () {
    return () => console.log(this.name)
  }}var person2 = { name: 'person2' }person1.show1()person1.show1.call(person2)person1.show2()person1.show2.call(person2)person1.show3()()person1.show3().call(person2)person1.show3.call(person2)()person1.show4()()person1.show4().call(person2)person1.show4.call(person2)()
Nach dem Login kopieren

一、this的指向

百度、谷歌上输入“this的指向”关键字,大几千条文章肯定是有的,总不至于为了全方面、无死角的掌握它就要将所有的文章都看一遍吧?所以不如梳理出一个稳固的框架,顺着我们的思路来填充它。

思维导图

Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

本节精华:

  • this 总是(非严格模式下)指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境;
  • 除了不常用的with和eval的情况,具体到实际应用中,this指向大概可以分为四种:
    • 作为对象的方法调用;
    • 作为普通函数调用;
    • 构造器调用;
    • call 或 apply调用;
    • 箭头函数中,this指向函数上层作用域的this;
  • 构造器普通函数的区别在于被调用的方式
  • A,call(B) => 可以理解成在B的作用域内调用了A方法;

分析

1、作为对象的方法调用

当函数作为对象的方法被调用时,this指向该对象

var obj = {
    a: 'yuguang',
    getName: function(){
        console.log(this === obj);
        console.log(this.a);
    }};obj.getName(); // true yuguang
Nach dem Login kopieren

2、作为普通函数调用

当函数不作为对象的属性被调用,而是以普通函数的方式,this总是指向全局对象(在浏览器中,通常是Window对象)

window.name = 'yuguang';var getName = function(){
    console.log(this.name);};getName(); // yuguang
Nach dem Login kopieren

或者下面这段迷惑性的代码:

window.name = '老王'var obj = {
    name: 'yuguang',
    getName: function(){
        console.log(this.name);
    }};var getNew = obj.getName;getNew(); // 老王
Nach dem Login kopieren

而在ES5的严格模式下,this被规定为不会指向全局对象,而是undefined

3、构造器调用

除了一些内置函数,大部分Js中的函数都可以成为构造器,它们与普通函数没什么不同

构造器普通函数的区别在于被调用的方式

Frage und Antwort:

Bitte sprechen Sie über die Arten von Zeigerfunktionen, die diesen Zeiger innerhalb einer Funktion ändern, und was sind ihre Unterschiede? In welche Arten von Richtungen lässt sich das unterteilen?

Fragen zur Code-Analyse:

var MyClass = function(){
    this.name = 'yuguang';}var obj = new MyClass();obj.name; // yuguang
Nach dem Login kopieren

1. Der Sinn davon

🎜🎜Geben Sie das Schlüsselwort „Punkt davon“ bei Baidu und Google ein, aber es ist nicht allumfassend. , Um es ohne blinde Flecken zu meistern, müssen Sie alle Artikel lesen, oder? Deshalb ist es besser, einen soliden Rahmen zu schaffen und ihn nach unseren Vorstellungen auszufüllen. 🎜🎜Mind Map🎜🎜Bildbeschreibung hier einfügen🎜 🎜Die Wesentlicher Teil dieses Abschnitts: 🎜🎜🎜Dies zeigt immer auf ein Objekt (im nicht strikten Modus), und das spezifische Objekt, auf das gezeigt wird, wird zur Laufzeit dynamisch an die Ausführungsumgebung der Funktion gebunden, nicht an die Funktion Die Umgebung, wenn sie deklariert wird; 🎜🎜Mit Ausnahme der ungewöhnlichen Situationen mit und eval kann dieser Zeiger in tatsächlichen Anwendungen grob in vier Typen unterteilt werden: 🎜🎜als Methodenaufruf eines Objekts; 🎜🎜als gewöhnlicher Funktionsaufruf; 🎜🎜 Konstruktoraufruf; 🎜🎜aufrufen oder anwenden 🎜🎜In einer Pfeilfunktion zeigt dies im oberen Bereich der Funktion an; wird aufgerufen;🎜🎜A,call(B) => Es kann verstanden werden, dass Methode A im Rahmen von B aufgerufen wird;🎜🎜🎜Analyse🎜🎜🎜1 🎜🎜Wenn die Funktion ein Objekt ist. Wenn eine Methode aufgerufen wird, <code>zeigt dies auf das Objekt🎜
var MyClass = function () {
    this.name = 1;
    return {
        name: 2
    }}var myClass = new MyClass(); console.log('myClass:', myClass); // { name: 2}
Nach dem Login kopieren
🎜🎜2 Wird als gewöhnliche Funktion aufgerufen🎜🎜🎜Wenn die Funktion nicht als Attribut aufgerufen wird des Objekts, aber als gewöhnliche Funktion ist dies immer ein Punkt auf das globale Objekt (im Browser normalerweise das Window-Objekt) 🎜
var obj1 = {
    name: 1,
    getName: function (num = '') {
        return this.name + num;
    }};var obj2 = {
    name: 2,};// 可以理解成在 obj2的作用域下调用了 obj1.getName()函数console.log(obj1.getName()); // 1console.log(obj1.getName.call(obj2, 2)); // 2 + 2 = 4console.log(obj1.getName.apply(obj2, [2])); // 2 + 2 = 4
Nach dem Login kopieren
🎜 oder den folgenden verwirrenden Code: 🎜
this.val = 2;var obj = {
    val: 1,
    getVal: () => {
        console.log(this.val);
    }}obj.getVal(); // 2
Nach dem Login kopieren
Nach dem Login kopieren
🎜 Im strengen Modus von ES5 ist dies festgelegt Nicht auf das globale Objekt verweisen, sondern auf undefiniert🎜🎜🎜3. Konstruktoraufruf🎜🎜🎜Mit Ausnahme einiger integrierter Funktionen können die meisten Funktionen in Js zu Konstruktoren werden. Sie unterscheiden sich nicht von gewöhnlichen Funktionen🎜🎜🎜Konstruktoren🎜und🎜gewöhnlich Der Unterschied zwischen Funktionen 🎜 liegt in der Art und Weise, wie aufgerufen wird: 🎜 Wenn der neue Operator eine Funktion aufruft, gibt er immer ein Objekt zurück, und dieses zeigt normalerweise auf dieses Objekt 🎜
var obj = {
    name: '1',
    getName: function (params) {
        console.log(this.name)
    }};obj.getName();var getName2 = obj.getName;getName2();
Nach dem Login kopieren
Nach dem Login kopieren
🎜 Wenn eine Funktion jedoch explizit ein Objekt zurückgibt, wird das Ergebnis dieser Operation schließlich dieses Objekt zurückgeben. 🎜
var getDomById = function (id) {
    return document.getElementById(id);};getDomById('p1') //dom节点
Nach dem Login kopieren
Nach dem Login kopieren
🎜Solange der Konstruktor keine Daten explizit zurückgibt oder Daten vom Nicht-Objekttyp zurückgibt, treten die oben genannten Probleme nicht auf. 🎜🎜🎜4. Aufrufen oder Anwenden des Aufrufs🎜🎜🎜Im Vergleich zu gewöhnlichen Funktionsaufrufen kann durch Aufrufen und Anwenden das Dies der Funktion dynamisch geändert werden. 🎜
var getDomById = document.getElementByIdgetDomById('p1') // Uncaught TypeError: Illegal invocation(非法调用)
Nach dem Login kopieren
Nach dem Login kopieren
🎜🎜5. Die Pfeilfunktion erstellt kein eigenes Dies. Es erbt dies nur von der oberen Ebene seiner eigenen Bereichskette. 🎜

因此,在下面的代码中,传递给setInterval的函数内的this与封闭函数中的this值相同:

this.val = 2;var obj = {
    val: 1,
    getVal: () => {
        console.log(this.val);
    }}obj.getVal(); // 2
Nach dem Login kopieren
Nach dem Login kopieren

常见的坑

就像标题一样,有的时候this会指向undefined

情况一

var obj = {
    name: '1',
    getName: function (params) {
        console.log(this.name)
    }};obj.getName();var getName2 = obj.getName;getName2();
Nach dem Login kopieren
Nach dem Login kopieren

这个时候,getName2()作为普通函数被调用时,this指向全局对象——window。

情况二

当我们希望自己封装Dom方法,来精简代码时:

var getDomById = function (id) {
    return document.getElementById(id);};getDomById('p1') //dom节点
Nach dem Login kopieren
Nach dem Login kopieren

那么我们看看这么写行不行?

var getDomById = document.getElementByIdgetDomById('p1') // Uncaught TypeError: Illegal invocation(非法调用)
Nach dem Login kopieren
Nach dem Login kopieren

这是因为:

  • 当我们去调用document对象的方法时,方法内的this指向document
  • 当我们用getId应用document内的方法,再以普通函数的方式调用,函数内容的this就指向了全局对象。

利用call和apply修正情况二

document.getElementById = (function (func) {
    return function(){
        return func.call(document, ...arguments)
    }})(document.getElementById) // 利用立即执行函数将document保存在作用域中
Nach dem Login kopieren

Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

二、call和apply

不要因为它的“强大”而对它产生抗拒,了解并熟悉它是我们必须要做的,共勉!

思维导图

Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

1.call和apply区别

先来看区别,是因为它们几乎没有区别,下文代码实例call和apply都可以轻易的切换。

当它们被设计出来时要做到的事情一摸一样,唯一的区别就在于传参的格式不一样

  • apply接受两个参数
    • 第一个参数指定了函数体内this对象的指向
    • 第二个参数为一个带下标的参数集合(可以是数组或者类数组)
  • call接受的参数不固定
    • 第一个参数指定了函数体内this对象的指向
    • 第二个参数及以后为函数调用的参数

因为在所有(非箭头)函数中都可以通过arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,它本身就是一个类数组,我们apply在实际使用中更常见一些。

call是包装在apply上面的语法糖,如果我们明确的知道参数数量,并且希望展示它们,可以使用call。

当使用call或者apply的时候,如果我们传入的第一个参数为null,函数体内的this会默认指向宿主对象,在浏览器中则是window

借用其他对象的方法

我们可以直接传null来代替任意对象

Math.max.apply(null, [1, 2, 3, 4, 5])
Nach dem Login kopieren

2.call和apply能做什么?

使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数——来时MDN

  • 调用构造函数来实现继承;
  • 调用函数并且指定上下文的 this;
  • 调用函数并且不指定第一个参数;

1.调用构造函数来实现继承

通过“借用”的方式来达到继承的效果:

function Product(name, price) {
	this.name = name;
	this.price = price;}function Food(name, price) {
	Product.call(this, name, price); //
	this.category = food;}var hotDog = new Food('hotDog', 20);
Nach dem Login kopieren

2.调用函数并且指定上下文的 this

此时this被指向了obj

function showName() {
    console.log(this.id + ':' + this.name);};var obj = {
    id: 1,
    name: 'yuguang'};showName.call(obj)
Nach dem Login kopieren

3.使用call单纯的调用某个函数

Math.max.apply(null, [1,2,3,10,4,5]); // 10
Nach dem Login kopieren

Detaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können

三、模拟实现一个call

先来看一下call帮我们需要做什么?

var foo = {
	value: 1};function show() {
	console.log(this.value);};show.call(foo); //1
Nach dem Login kopieren

就像解方程,要在已知条件中寻找突破哦口:

  • call 使得this的指向变了,指向了foo;
  • show 函数被执行了;
  • 传入的参数应为 this + 参数列表;

第一版代码

上面提到的3点,仅仅完成了一点,且传入的参数

var foo = {
    value: 1};function show() {
    console.log(this.value);};Function.prototype.setCall = function (obj) {
    console.log(this); // 此时this指向show
    obj.func = this; // 将函数变成对象的内部属性
    obj.func(obj.value); // 指定函数
    delete obj.func // 删除函数,当做什么都没发生~}show.setCall(foo);
Nach dem Login kopieren

第二版代码

为了解决参数的问题,我们要能获取到参数,并且正确的传入:

var foo = {
    value: 1};function show(a, b) {
    console.log(this.value);
    console.log(a + b);};Function.prototype.setCall = function (obj) {
    obj.fn = this; // 将函数变成对象的内部属性
    var args = [];
    for(let i = 1; i <p>此时,我们就可以做到,传入多个参数的情况下使用call了,但是如果你仅想用某个方法呢?</p><p><strong>第三版代码</strong></p><pre class="brush:php;toolbar:false">Function.prototype.setCall = function (obj) {
    var obj = obj || window;
    obj.fn = this;
    var args = [];
    for(var i = 1, len = arguments.length; i <p><strong>四、bind</strong></p><blockquote><p>bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用 —— MDN</p></blockquote><p>提到了<strong>call</strong>和<strong>apply</strong>,就绕不开<strong>bind</strong>。我们试着来模拟一个bind方法,以便加深我们的认识:</p><pre class="brush:php;toolbar:false">Function.prototype.bind = function (obj) {
    var _this = this; // 保存调用bind的函数
    var obj = obj || window; // 确定被指向的this,如果obj为空,执行作用域的this就需要顶上喽
    return function(){
        return _this.apply(obj, arguments); // 修正this的指向
    }};var obj = {
    name: 1,
    getName: function(){
        console.log(this.name)
    }};var func = function(){
    console.log(this.name);}.bind(obj);func(); // 1
Nach dem Login kopieren

这样看上去,返回一个原函数的拷贝,并拥有指定的 this 值,还是挺靠谱的哦~

写在最后

Der erste Teil des grundlegenden Teils der internen JavaScript-Kenntnisse. Zusammenfassend lässt sich sagen, dass diese Serie von Xian Yu sehr gefördert und inspiriert wurde. Diese Serie enthält etwa 15 Artikel, die wir alle am häufigsten interviewen, die aber bei der Arbeit oft ignoriert werden . .

Verwandte kostenlose Lernempfehlungen: Javascript(Video)

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterungen zu diesem Hinweis, damit Sie ihn verstehen, aufrufen und in einem Artikel anwenden können. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:csdn.net
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage