Mather Blog

先进到和魔法无异的 JavaScript this

默认分类 0 评

this 为何而生

随着你的使用模式越来越复杂,显示传递上下文对象会让代码变得越来越乱,使用 this 这不会。

this 提供了一种更优雅得方式来隐式“传递”一个对象引用,因此可以将 API 设计得更加简洁并且易于复用。

this 在任何情况下都不指向函数的词法作用域,this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用

把人绕晕的题目

开发者往往会把理解 this 的过程复杂化,并把它作为进阶中高级开发者的门槛。即使是非常有经验的 JavaScript 开发者也很难说清楚它到底指向什么。

var fullName = 'a';
var obj = {
    fullName: 'b',
    prop:{
        fullName: 'c',
        getFullName: function(){
            console.log(this);
            return this.fullName
        }
    }
}

console.log(obj.prop.getFullName());

var test = obj.prop.getFullName;
console.log(test());
console.log(obj.prop.getFullName())

严格来说 getFullName() 函数不属于 obj 对象,但调用位置会使用 obj 上下文来引用函数。

//console.log(this);
{fullName: "c", getFullName: ƒ}

c

getFullName() 函数被调用时,obj 对象包含了它,隐式绑定规则会把函数调用的 this 绑定到 obj 上下文,因此 thisobj.prop 是一样的;

console.log(test())
a

test 变量通过别名的方式引用了 getFullName() 函数,此时 test() 是一个不带任何修饰的函数调用,因此应用了默认绑定 ,this 指向全局对象


var num = 1;
var myObject = {
    num: 2,
    add: function() {
        this.num = 3;
        (function() {
            console.log(this.num);
            this.num = 4;
        })();
        console.log(this.num);
    },
    sub: function() {
        console.log(this.num)
    }
}


myObject.add();

console.log(myObject.num);

console.log(num);

var sub = myObject.sub;
sub();
myObject.add()

add 函数中含有匿名函数,在匿名函数中 this 被重新绑定到全局对象,所以匿名函数中的 this 是 window ;最后修改 window.num 为 4

1

add 函数执行时 隐式绑定myObject 上下文,一般情况下此时的 this 就是 myObject

this.num = 3; 率先将 myObject.num 赋值为 3

3
console.log(myObject.num)

add 函数执行后修改了 myObject.num 为 3

3
console.log(num)

这里的 num 指的是 window.numadd 函数中的匿名函数执行后修改了 window.num 为 4

4
sub()

sub 变量是 myObject.sub() 函数的引用,此时 sub() 是一个不带任何修饰的函数调用,因此应用了默认绑定 ,this 指向全局对象,即是 window.num

4

绑定规则

默认绑定
隐式绑定
显式绑定
new 绑定

参考

JavaScript 数据类型和检测方式

发表评论
撰写评论