Maison  >  Article  >  interface Web  >  Explication détaillée de son utilisation en Javascript

Explication détaillée de son utilisation en Javascript

不言
不言avant
2019-03-23 09:36:422387parcourir

Cet article vous apporte une explication détaillée de son utilisation en Javascript. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Avant de comprendre cela en javascript, comprenez d'abord la portée.

Les portées sont divisées en deux types :

1. Portée lexicale : le moteur recherche les variables avec des identifiants de nom dans la portée actuelle ou les sous-portées imbriquées. (Comment et où le moteur recherche. Le processus de définition se produit pendant la phase d'écriture du code)
2. Portée dynamique : une portée qui est déterminée dynamiquement au moment de l'exécution.

La différence entre la portée lexicale et la portée dynamique est la suivante : la portée lexicale est déterminée lors de l'écriture du code ou de la définition ;

Règles de liaison pour ceci

Ceci est lié lorsqu'il est appelé, en fonction de l'emplacement d'appel de la fonction. On peut en déduire que dans des circonstances normales (en mode non strict), cela liera l'objet en fonction du contexte de l'appel de fonction (pile d'appels).

1. Liaison par défaut

Liaison par défaut : la liaison par défaut signifie qu'en mode non strict et qu'aucune autre règle de liaison n'est utilisée, elle est appelée en fonction de la fonction (pile d'appels) Contexte à lier objets (objets globaux). (En mode strict, undefined est lié)

Par exemple :

function foo() {
    console.log(this.a);
};
function bar() {
    var a = 3;
    foo();
}
var a = 2;
bar();  //调用栈在全局作用域,this绑定全局对象

运行结果为: 2
//加上"use strict"运行结果则会变成this is undefined

Lorsque la fonction est appelée ici, la liaison par défaut est utilisée, et le contexte de l'appel de fonction (pile d'appel ) est une portée globale, elle est donc liée à l'objet global (global).

eg2:
function foo() {
    console.log(this.a)
};
var a = 2;
(function() {
    "use strict"
    foo();
})();

运行结果为: 2

Il convient de noter ici : pour la liaison par défaut, ce qui détermine cet objet de liaison n'est pas si l'emplacement appelant est en mode strict, mais si le corps de la fonction est en mode strict (le corps de la fonction est en mode strict, alors cette liaison n'est pas définie ; sinon elle est liée à l'objet global). De plus : Bien qu’il soit possible de lier mode strict et mode non strict, il est préférable de ne pas les mélanger.

Les références indirectes appliquent généralement des règles de liaison par défaut.

eg:
function foo() {
    console.log(this.a);
};
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo();   //3
(p.foo = o.foo)();  //2

La valeur de retour de l'expression d'affectation p.foo = o.foo fait directement référence à la fonction cible foo.

2. Liaison implicite

Liaison implicite : appelée par l'objet contextuel, liée à l'objet contextuel.

Par exemple :

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2,
    foo: foo
};
obj.foo();    //2
foo();        //undefined

Dans ce code, foo() est ajouté à l'objet obj en tant qu'attribut de référence. Lorsque obj appelle cette fonction d'attribut de référence, il utilisera cet attribut de référence. . Contexte, cela sera lié à l'objet obj. (À proprement parler, cette fonction n'appartient pas à l'objet obj, mais sert uniquement d'attribut de référence). Appartient à la liaison implicite.

L'exécution directe de la fonction foo() ci-dessous n'est pas une référence à l'objet obj, donc l'objet contextuel est l'objet global. Par conséquent, cela est forcément indéfini. Appartient à la liaison par défaut.

Seule la couche supérieure ou la dernière de la chaîne de référence d'objet joue un rôle dans l'emplacement appelant.

Remarque :

Les fonctions implicitement liées perdront l'objet lié. À ce moment, il appliquera la liaison par défaut, la liant à l'objet global ou non défini, selon qu'il s'agit d'un mode strict.
par exemple :

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2;
    foo: foo
}
var bar = obj.foo;
var a = 'biubiubiu';
bar();

运行结果:"biubiubiu"

Analyse : Il semble que bar soit une référence à obj.foo. En fait, bar fait directement référence à la fonction foo, qui est un simple appel de fonction, elle est donc en fait liée. par défaut.

Le passage de paramètres est une affectation implicite, donc lorsqu'il est transmis à la fonction, il sera également implicitement attribué.
par exemple :

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2,
    foo: foo
};
function bar(fn) {
    fn();
};
var a = "biubiubiu";
bar(obj.foo);

运行结果: "biubiubiu"

Analyse : En fait, les paramètres sont également implicitement attribués, mais les paramètres sont passés dans la fonction et exécutés dans la fonction. À l'heure actuelle, la fonction foo est également directement référencée, il s'agit donc également d'un simple appel de fonction, utilisant la liaison par défaut.

Transmettez les fonctions aux fonctions intégrées du langage. (Essentiellement similaire à la situation ci-dessus, remplacez la fonction auto-déclarée par la fonction intégrée du langage) Il est courant que les fonctions de rappel perdent cela, et la fonction qui appelle la fonction de rappel peut modifiez également cela.

3. Liaison explicite

Liaison explicite : Liez-le directement à l'objet spécifié. La plupart des fonctions en Javascript et des fonctions que vous créez peuvent utiliser ces deux méthodes de liaison explicites.

1, .call()
2, .apply()
Ces deux méthodes de liaison, le premier paramètre est l'objet lié à ceci. (Si le paramètre transmis est une valeur primitive (type chaîne, type booléen, type numérique), la valeur primitive sera convertie en une forme objet (nouvelle chaîne, nouveau booléen, nouveau nombre). C'est appelé : Emballage)

Par exemple :

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

运行结果: 2

Cependant, afficher la reliure ne résout pas le problème de la perte de reliure. A ce moment, un nouvel ami arrive - une reliure rigide (bind).

3. .bind() (La liaison matérielle est un scénario courant, donc es5 fournit la méthode intégrée Function.prototype.bind.)
bind() will Renvoie une nouvelle fonction d'encodage, la lie aux paramètres spécifiés et appelle la fonction.

Par exemple :

function foo(e) {
    console.log(this.a + e);
    return this.a + e;
};
var obj = {
    a: 2
}
var bar = foo.bind(obj); //新编码函数
var b = bar(3); // 2 3
console.log(b); // 5

bind() Il existe également une fonction  : sauf la première Les paramètres autres que les paramètres utilisés pour lier ceci sont transmis à la fonction sous-jacente ( s'applique partiellement , qui est un type de " curry ").

这里涉及到一个概念:把null或者undefined作为this的绑定对象传入call、apply、bind,这些值在调用的时候会被忽略,实际应用默认绑定规则。
应用场景:
1、使用apply()展开一个数组,并作为参数传递给一个函数。
2、bind()对参数进行柯里化(预先设置一些参数)。

举个栗子:

function foo(a,b) {
    console.log("a:" + a + ",b:" + b);
};
//数组“展开”成参数
foo.apply(null,[2,3]);  //a:2,b:3
//bind()柯里化
var bar = foo.bind(null,2);
bar(3);  //a:2,b:3

解析:传入一个参数作为this绑定对象,如果不传则使用占位符(null),此时会使用默认绑定规则。

上面这个例子可能会产生一定的副作用,如果需要运用这种场景并且更加安全。可以创建一个空对象(可以用任意喜欢的名字来命名)。

var ∅ = Object.create(null);
//上面这个例子就可以改写为:
foo.apply(∅,[2,3]); //a:2,b:3
var bar = foo.bind(∅,2);
bar(3);  //a:2,b:3

注意:硬绑定之后不能使用隐式绑定和显式绑定对this进行修改
在这里介绍一种软绑定的方法softBind()检查this绑定到全局对象或者undefined后,绑定this到指定的默认对象。绑定后效果和硬绑定一样,但是保留隐式绑定或者显式绑定修改this的能力。

四、new绑定

Javascript中的new机制与面向类语言的完全不同。在Javascript中,构造函数只是一些使用new操作符时被调用的函数,不属于一个类,也不会实例化一个类。称为对函数的“构造调用”。

举个栗子:

function foo(a) {
    this.a = a;
}
var bar = new foo(2);
console.log(bar.a); //2

使用new的过程会创建一个全新的对象,this会绑定这个新对象。如果函数没有返回其他对象,则new表达式函数调用会返回该新对象。(这个新对象会连接prototype)

四种绑定规则的优先级为:new>显式>隐式>默认

箭头函数

箭头函数是根据外层作用域(函数或全局)来决定this。(词法作用域取代this机制)
箭头函数this会绑定调用时的对象,且箭头函数的绑定无法修改(new也不行)。

其实可以理解为,箭头函数的this在词法上继承的是它所在的作用域(函数或全局)的this,而它继承的函数作用域的this绑定的是在该函数调用上下文对象,所以箭头函数的this间接的绑定在调用上下文对象。

简述: 箭头函数this(绑定作用域this)-- 作用域this(绑定在调用上下文对象)。

故:箭头函数this == 调用的上下文对象

举个栗子:

function foo() {
    setTimeout(function() {
        //这里的this在词法上继承自foo()
        console.log(this.a);
    },100);
};
var obj = { a: 2 };
foo.call(obj);  //2

其实这个栗子也等价于:

function foo() {
    var that = this;  //lexical capture of this
    setTimeout(function() {
        console.log(self.a)
    },100);
}
...与上面一样

所以,有两种风格:this风格(四种规则)词法作用域风格(that = this和箭头函数)可供使用。使用时尽量避免混用,否则会造成难以维护的后果。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的JavaScript视频教程栏目!

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer