码迷,mamicode.com
首页 > 其他好文 > 详细

对this关键字的深入探究

时间:2018-02-17 18:39:00      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:window   无法   关键字   src   理解   规则   glob   efi   set   

  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绑定 > 显式绑定 > 隐式绑定 > 默认绑定

未完待续

 

 

对this关键字的深入探究

标签:window   无法   关键字   src   理解   规则   glob   efi   set   

原文地址:https://www.cnblogs.com/PeriHe/p/8452053.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!