Maison >interface Web >js tutoriel >Compréhension approfondie de cela dans ECMA Javascript (avec exemples)

Compréhension approfondie de cela dans ECMA Javascript (avec exemples)

不言
不言avant
2018-11-24 14:05:592258parcourir

Cet article vous apporte une compréhension approfondie de cela en Javascript ECMA (avec des exemples). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Il s'agit en fait d'une liaison qui se produit lorsque la fonction est appelée, et ce vers quoi elle pointe dépend entièrement de l'endroit où la fonction est appelée (c'est-à-dire de la manière dont la fonction est appelée).

Quatre règles : (JS vous ne connaissez pas)

1. Liaison par défaut

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

si ou. not En mode strict, dans le contexte d'exécution global (en dehors de tout corps de fonction) ceci fait référence à l'objet global. (MDN)
En mode strict, ceci conservera sa valeur lorsqu'il entrera dans le contexte d'exécution. Si celle-ci n'est pas définie par le contexte d'exécution, elle restera indéfinie. (MDN)

function foo() {
    "use strict";
    console.log( this.a );
}
var a = 2;
foo(); // TypeError: this is undefined

2. Liaison/perte implicite

Lorsque des fonctions sont appelées en tant que méthodes dans des objets, c'est l'objet qui appelle la fonction, et la liaison n'est affectée que par le référence du membre le plus proche. (MDN)

//隐式绑定
function foo() {
    console.log( this.a );
}
var obj2 = {
    a: 42,
    foo: foo
};
var obj1 = {
    a: 2,
    obj2: obj2
};
obj1.obj2.foo(); // 42
//隐式丢失
function foo() {
    console.log( this.a );
}
function doFoo(fn) {
    // fn 其实引用的是 foo
    fn(); // <-- 调用位置!
}
var obj = {
    a: 2,
    foo: foo
};
var a = "oops, global"; // a 是全局对象的属性
doFoo( obj.foo ); // "oops, global"

3. Liaison d'affichage

Si vous souhaitez transmettre la valeur de this d'un contexte à un autre, vous devez utiliser la méthode call ou apply. (MDN)
Appeler f.bind(someObject) créera une fonction avec le même corps de fonction et la même portée que f, mais dans cette nouvelle fonction, elle sera définitivement liée au premier paramètre de bind, quelle que soit la manière dont cette fonction. est appelé.

var obj = {
    count: 0,
    cool: function coolFn() {
    if (this.count < 1) {
        setTimeout( function timer(){
            this.count++; // this 是安全的
                            // 因为 bind(..)
            console.log( "more awesome" );
            }.bind( this ), 100 ); // look, bind()!
        }
    }
};
obj.cool(); // 更酷了。

Liaison dure

Crée une fonction wrapper qui transmet tous les paramètres et renvoie toutes les valeurs reçues.
La liaison matérielle réduira considérablement la flexibilité de la fonction. Après avoir utilisé la liaison matérielle, vous ne pouvez pas utiliser la liaison implicite ou la liaison explicite pour modifier cela.

// 简单的辅助绑定函数
function bind(fn, obj) {
    return function() {
        return fn.apply( obj, arguments );
    };
}

Liaison souple

Spécifiez un objet global et une valeur autre que non définie pour la liaison par défaut, vous pourrez alors obtenir le même effet qu'une liaison dure tout en conservant la liaison implicite Ou lier explicitement le possibilité de modifier cela.

Function.prototype.softBind = function(obj) {
    var fn = this;
    var curried = [].slice.call( arguments, 1 );// 捕获所有 curried 参数
    var bound = function() {
        return fn.apply(
            (!this || this === (window || global))?obj : this
            curried.concat.apply( curried, arguments )
        );
    };
    bound.prototype = Object.create( fn.prototype );
    return bound;
};

4. nouvelle liaison

Lorsqu'une fonction est utilisée comme constructeur (à l'aide du nouveau mot-clé), elle est liée au nouvel objet en cours de construction. (MDN)
Utilisez new pour appeler une fonction, ou lorsqu'un appel de constructeur se produit, les opérations suivantes seront automatiquement effectuées (JS vous ne connaissez pas)

  1. Créer (ou construct ) un objet complètement nouveau.

  2. Ce nouvel objet sera connecté par [[ prototype ]].

  3. Ce nouvel objet sera lié au this de l'appel de fonction.

  4. Si la fonction ne renvoie aucun autre objet, alors l'appel de fonction dans la nouvelle expression renverra automatiquement ce nouvel objet.

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

Priorité à quatre règles

nouvelle liaison> liaison explicite> liaison par défaut>

    la fonction est appelée en new (nouvelle liaison) ? Si tel est le cas, cela est lié à l'objet nouvellement créé.
  1.  var bar = new foo()
  2. La fonction est-elle appelée via un appel, une application (liaison explicite) ou une liaison matérielle ? Si tel est le cas, cela est lié à l'objet spécifié.
  3. De plus :
    En cas de liaison null ou undefined , les règles de liaison par défaut sont effectivement appliquées.

     var bar = foo.call(obj2)
  4. La fonction est-elle appelée dans un objet contextuel (implicitement lié) ? Si tel est le cas, cela est lié à cet objet contextuel.
  5.  var bar = obj1.foo()
  6. Si aucun des deux, utilisez la liaison par défaut. S'il est en mode strict, il est lié à undefined , sinon il est lié à l'objet global.
  7.  var bar = foo()
    Où :

    Les fonctions de référence indirecte appliqueront les règles de liaison par défaut

    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
Exceptions

1. Fonction flèche

La fonction flèche n'utilise pas les quatre règles standard de celle-ci, mais la détermine en fonction de la portée externe (fonction ou globale).

Dans les fonctions fléchées, ceci est cohérent avec le this du contexte lexical englobant. (MDN)

Les fonctions fléchées héritent de la liaison this de l'appel de fonction externe (peu importe à quoi cela est lié). C'est en fait le même mécanisme que self = this.
Les liaisons des fonctions fléchées ne peuvent pas être modifiées.

2. nodejs

setTimeout(function() { 
    console.log(this) 
    //浏览器中:window 
    //nodejs中:Timeout实例
}, 0)
Autres explications

https://www.zhihu.com/questio. ..

func(p1, p2) est équivalent à

func.call(undefined, p1, p2)

obj.child.method(p1, p2) est équivalent à

obj .child.method.call(obj.child, p1, p2)


Si le contexte que vous transmettez est nul ou indéfini, alors l'objet window est le contexte par défaut (le contexte par défaut en mode strict est indéfini)

Exemple

    var number = 50;
    var obj = {
        number: 60,
        getNum: function () {
        var number = 70;
        return this.number;
    }
    }; 

    alert(obj.getNum());
    alert(obj.getNum.call());
    alert(obj.getNum.call({number:20}));

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