对this关键字的深入探究

Posted PeriHe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对this关键字的深入探究相关的知识,希望对你有一定的参考价值。

  this无疑是javascript中特别复杂的机制了,最使我们困扰的就是this的指向,仅以本文对我所理解的this做一个总结和记录。每一句话都是重点!文章参考《你不知道的javascript》。

  首先需要对this有一个大概的理解:每个函数的this都是在调用时被绑定的,完全取决于函数的调用位置。

绑定规则

  当我们找到函数的调用位置以后,需要判断应用了哪条绑定规则,绑定规则分为四种:默认绑定,隐式绑定,显式绑定,new绑定。

一,默认绑定

  这是最常用的函数调用类型:独立函数调用。可以把这条规则看作是无法应用其他规则时的默认应用。

  如下,这里的foo()是直接使用不带任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则。

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

  注意虽然this的绑定规则完全取决于调用位置,但是只有foo()运行在非严格模式下默认绑定才能绑定到全局对象。严格模式下与foo()的调用位置无关。如果使用严格模式,那么全局对象将无法使用默认绑定,因此会绑定到undefined。

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

  报错:

 

二,隐式绑定

  这条规则需要考虑的是调用位置是否有上下文对象,或者说是否被某个对象拥有或包含。当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象像下面这个样子,调用foo()时this被绑定到obj,因此this.a和obj.a是一样的:

  对象属性引用链中只有最后一层会影响调用位置。

function foo() {
    console.log(this.a);
};
var obj2 = {
    a: 32,
    foo: foo
}
var obj1 = {
    a: 2,
    obj2: obj2
};
obj1.obj2.foo();    //32

隐式丢失

  这也是最常见的this绑定问题了,被隐式绑定的函数会丢失绑定对象,也就是说会应用默认绑定,从而把this绑定到全局对象或者undefined上(取决于是否严格模式)。

  有以下几种情况:

  1.虽然bar是obj.foo的引用,但是实际上它引用的是foo函数本身,此时的bar便是一个不带任何修饰的函数调用,因此应用了默认样式。

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

  2.参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值。

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

  3.参数传入内置函数时也是一样

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2,
    foo: foo
}
var a = "global";
setTimeout(obj.foo, 100);    //global

三,显式绑定

  如果不想在对象内部包含函数引用,而想在某个对象上强制调用函数,可以使用call()和apply()方法,它们的第一个参数时对象,会把这个对象绑定到this。称之为显式绑定

  强制把foo的this绑定到obj,无论之后如何调用bar,总是会在obj上调用。

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2
}
var bar = function() {
    foo.call(obj);
}
bar();    //2
setTimeout(bar, 100);    //2
bar.call(window);    //2  

四,new绑定

  使用new来调用foo时,会构造一个新的对象并把它绑定到foo()调用中的this上。

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

优先级

  既然几种绑定规则讨论完了,那么我们来比较一下他们的优先级顺序。细节不做讨论,可以自行测试。总之结果是:new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

  也就是说:

  如果函数在new中调用,则this指向的是新创建的对象;再看是否通过call,apply调用,是的话this就指向指定的那个对象;然后看是否在某个上下文调用,如果是,就指向这个上下文对象;最后若都没有就是默认绑定了。

 

 

 

以上是关于对this关键字的深入探究的主要内容,如果未能解决你的问题,请参考以下文章

java深入探究11-基础加强

深入探究js中的隐式变量声明

Mysql索引:图文并茂,深入探究索引的原理和使用

深入理解JavaScript中的this关键字

深入理解this关键字

java深入探究12-框架整合