Heim > Web-Frontend > js-Tutorial > Erklären Sie in einfachen Worten, wie Sie „Apply', „Call' und „Bind' in Javascript verwenden

Erklären Sie in einfachen Worten, wie Sie „Apply', „Call' und „Bind' in Javascript verwenden

伊谢尔伦
Freigeben: 2016-12-01 10:07:19
Original
1451 Leute haben es durchsucht

Obwohl es viele Artikel online gibt, werden die meisten davon kopiert und eingefügt und sind schwer zu verstehen. Ich hoffe, dass ich durch diesen Artikel mein Verständnis von Anwenden, Aufrufen und Binden deutlich verbessern und einige davon auflisten kann wunderbare Verwendungsmöglichkeiten, um mein Gedächtnis zu vertiefen.

Erklären Sie in einfachen Worten, wie Sie „Apply, „Call und „Bind in Javascript verwenden

apply, call

In JavaScript existieren sowohl call als auch apply, um den Kontext zu ändern, wenn eine Funktion ausgeführt wird Ändern Sie den Zeiger innerhalb des Funktionskörpers.

Ein Hauptmerkmal von JavaScript besteht darin, dass Funktionen die Konzepte „Definitionskontext“ und „Laufzeitkontext“ sowie „Kontext kann geändert werden“ haben.

Beginnen wir mit einer Kastanie:

function fruits() {}
  
fruits.prototype = {
    color: "red",
    say: function() {
        console.log("My color is " + this.color);
    }
}
  
var apple = new fruits;
apple.say();    //My color is red
Nach dem Login kopieren

Aber wenn wir ein Objekt haben banane= {color : "gelb"} und wir die Say-Methode darauf nicht neu definieren wollen , dann können wir „Oder apply“ mit der Say-Methode von Apple aufrufen:

banana = {
    color: "yellow"
}
apple.say.call(banana);     //My color is yellow
apple.say.apply(banana);    //My color is yellow
Nach dem Login kopieren

Es ist also ersichtlich, dass „call“ und „apply“ dies scheinbar dynamisch ändern, wenn ein Objekt keine bestimmte Methode hat (hier eine Banane). Kastanie hat keine Say-Methode), aber es gibt andere (in dieser Kastanie hat Apple eine Say-Methode), wir können call oder apply verwenden, um mit anderen Objektmethoden zu arbeiten.

Der Unterschied zwischen Apply und Call

Bei Apply und Call sind die Funktionen genau gleich, aber die Art der Parameterannahme ist unterschiedlich. Beispielsweise gibt es eine Funktion, die wie folgt definiert ist:

var func = function(arg1, arg2) {
     
};
Nach dem Login kopieren

kann wie folgt aufgerufen werden:

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
Nach dem Login kopieren

wobei dies der Kontext ist, den Sie angeben möchten, kann dies der Fall sein sei irgendetwas. Ein JavaScript-Objekt (alles in JavaScript ist ein Objekt). Beim Aufruf müssen Parameter der Reihe nach übergeben werden, während „Apply“ die Parameter in ein Array einfügt.

In JavaScript ist die Anzahl der Parameter einer Funktion nicht festgelegt. Wenn Sie also Bedingungen anwenden möchten, verwenden Sie call, wenn die Anzahl Ihrer Parameter eindeutig bekannt ist.

Wenn Sie sich nicht sicher sind, verwenden Sie „Apply“, drücken Sie dann die Parameter in das Array und übergeben Sie sie. Wenn die Anzahl der Parameter unsicher ist, können alle Parameter innerhalb der Funktion über das Argumentarray durchlaufen werden.

Um das Gedächtnis zu festigen und zu vertiefen, sind hier einige häufige Anwendungen:

1. Zwischen Arrays anhängen

var array1 = [12 , "foo" , {name "Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
/* array1 值为  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */
Nach dem Login kopieren

2. Die maximale Summe abrufen Das Array Minimum value

var  numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers),   //458
    maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
Nach dem Login kopieren

number selbst hat keine Max-Methode, Math jedoch schon, sodass wir seine Methode mit call oder apply verwenden können.

3. Überprüfen Sie, ob es sich um ein Array handelt (vorausgesetzt, die toString()-Methode wurde nicht überschrieben)

functionisArray(obj){
    returnObject.prototype.toString.call(obj) === '[object Array]' ;
}
Nach dem Login kopieren

4. Verwenden Sie die Array-Methode für die Klasse (Pseudo-)Arrays

var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
Nach dem Login kopieren

In Javascript gibt es eine Objektstruktur namens Pseudo-Array. Was noch spezieller ist, ist das Arguments-Objekt sowie Aufrufe wie getElementsByTagName, document.childNodes usw. Die von ihnen zurückgegebenen NodeList-Objekte sind Pseudo-Arrays. Die Push-, Pop- und anderen Methoden unter Array können nicht angewendet werden.

Aber wir können Array.prototype.slice.call verwenden, um es in ein Objekt mit der Längeneigenschaft eines echten Arrays umzuwandeln, sodass domNodes alle Methoden unter Array anwenden kann.

Umfassendes Verständnis der Verwendung von „Apply“ und „Call“

Lassen Sie uns eine Interviewfrage ausleihen, um ein tieferes Verständnis von „Apply“ und „Call“ zu erlangen.

Definieren Sie eine Protokollmethode, damit sie die Methode console.log vertreten kann. Die übliche Lösung ist:

function log(msg) {
  console.log(msg);
}
log(1);    //1
log(1,2);    //1
Nach dem Login kopieren

Die obige Methode kann die grundlegendsten Anforderungen erfüllen, aber wann Wenn die Anzahl der Eingabeparameter unsicher ist, schlägt die obige Methode fehl. Zu diesem Zeitpunkt können Sie die Verwendung von apply oder call in Betracht ziehen. Beachten Sie, dass die Anzahl der übergebenen Parameter unsicher ist. Daher ist die Verwendung von apply die beste Methode wie folgt:

function log(){
  console.log.apply(console, arguments);
};
log(1);    //1
log(1,2);    //1 2
Nach dem Login kopieren

Die nächste Anforderung besteht darin, jeder Protokollnachricht ein „(app)“-Präfix hinzuzufügen, z. B.:

log("hello world");    //(app)hello world
Nach dem Login kopieren

Wie geht das eleganter? Zu diesem Zeitpunkt müssen Sie davon ausgehen, dass der Parameter arguments ein Pseudo-Array ist, ihn über Array.prototype.slice.call in ein Standard-Array konvertieren und dann die Array-Methode unshift wie folgt verwenden :

function log(){
  var args = Array.prototype.slice.call(arguments);
  args.unshift('(app)');
  
  console.log.apply(console, args);
};
Nach dem Login kopieren

bind

  说完了 apply 和 call ,再来说说bind。bind() 方法与 apply 和 call 很相似,也是可以改变函数体内 this 的指向。

  MDN的解释是:bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

  直接来看看具体如何使用,在常见的单体模式中,通常我们会使用 _this , that , self 等保存 this ,这样我们可以在改变了上下文之后继续引用到它。 像这样:

var foo = {
    bar : 1,
    eventBind: function(){
        var _this = this;
        $('.someClass').on('click',function(event) {
            /* Act on the event */
            console.log(_this.bar);     //1
        });
    }
}
Nach dem Login kopieren

由于 Javascript 特有的机制,上下文环境在 eventBind:function(){ } 过渡到 $('.someClass').on('click',function(event) { }) 发生了改变,上述使用变量保存 this 这些方式都是有用的,也没有什么问题。当然使用 bind() 可以更加优雅的解决这个问题:

var foo = {
    bar : 1,
    eventBind: function(){
        $('.someClass').on('click',function(event) {
            /* Act on the event */
            console.log(this.bar);      //1
        }.bind(this));
    }
}
Nach dem Login kopieren

在上述代码里,bind() 创建了一个函数,当这个click事件绑定在被调用的时候,它的 this 关键词会被设置成被传入的值(这里指调用bind()时传入的参数)。因此,这里我们传入想要的上下文 this(其实就是 foo ),到 bind() 函数中。然后,当回调函数被执行的时候, this 便指向 foo 对象。再来一个简单的栗子:

var bar = function(){
console.log(this.x);
}
var foo = {
x:3
}
bar(); // undefined
var func = bar.bind(foo);
func(); // 3
Nach dem Login kopieren

这里我们创建了一个新的函数 func,当使用 bind() 创建一个绑定函数之后,它被执行的时候,它的 this 会被设置成 foo , 而不是像我们调用 bar() 时的全局作用域。

有个有趣的问题,如果连续 bind() 两次,亦或者是连续 bind() 三次那么输出的值是什么呢?像这样:

var bar = function(){
    console.log(this.x);
}
var foo = {
    x:3
}
var sed = {
    x:4
}
var func = bar.bind(foo).bind(sed);
func(); //?
  
var fiv = {
    x:5
}
var func = bar.bind(foo).bind(sed).bind(fiv);
func(); //?
Nach dem Login kopieren

答案是,两次都仍将输出 3 ,而非期待中的 4 和 5 。原因是,在Javascript中,多次 bind() 是无效的。更深层次的原因, bind() 的实现,相当于使用函数在内部包了一个 call / apply ,第二次 bind() 相当于再包住第一次 bind() ,故第二次以后的 bind 是无法生效的。

apply、call、bind比较

  那么 apply、call、bind 三者相比较,之间又有什么异同呢?何时使用 apply、call,何时使用 bind 呢。简单的一个栗子:

var obj = {
    x: 81,
};
  
var foo = {
    getX: function() {
        return this.x;
    }
}
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81
Nach dem Login kopieren

    三个输出的都是81,但是注意看使用 bind() 方法的,他后面多了对括号。

 也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

 再总结一下:

apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;

apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;

apply 、 call 、bind 三者都可以利用后续参数传参;

bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

Verwandte Etiketten:
Quelle:php.cn
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