JavaScript之this指向

this 是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。关于 this,经常会有一些误解:比如会把 this 理解成指向函数自身,又或者认为 this 指向函数的作用域。

其实,this 是在函数调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。因此,函数的不同使用场合,this 也有不同的值。那么我们该如何判断 this 呢?

可以按照下面的顺序来进行判断:

1.函数是否在 new 中调用(new绑定)?如果是的话,this 绑定的是新创建的对象。

首先,回想下 new 运算符会执行哪些操作:
a.创建(或者说构造)一个全新的对象
b.这个新对象会被执行[[Prototype]]连接
c.这个新对象会绑定到函数调用的 this
d.如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象
	function foo() {
        this.num = 10;
        return '';
    }
    function foo2() {
        this.num = 10;
        return 1;
    }
    function foo3() {
        this.num = 10;
        return [];
    }
    function foo4() {
        this.num = 10;
        return {};
    }
    function foo5() {
        this.num = 10;
        return function(){};
    }
    function foo6() {
        this.num = 10;
        return null;
    }
    console.log(new foo().num, new foo2().num, new foo3().num, new foo4().num, new foo5().num, new foo6().num);  // 10 10 undefined undefined undefined 10

2.函数是否通过 call,apply(显示绑定)或者bind(硬绑定)调用?如果是的话,this 绑定的是指定的对象。

	var obj = {
        num: 20
    };
    function foo() {
        this.num = 10;
        console.log(this);
    }
    foo();  // Window 对象
    foo.call(obj);  // {num: 10}
    foo.apply(obj);  // {num: 10}
    foo.bind(obj)();  // {num: 10}
call, apply, bind 都可以改变函数的 this 指向,区别是:
1.call, apply 将立即执行该函数,bind不执行函数,只返回一个可供执行的函数
2.调用方式不一样:
    call(this, arg1, arg2, arg3);
    apply(this, [arg1, arg2, arg3]);
    bind(this, arg1, arg2, arg3)();

3.函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上下文对象。

注:对象属性引用链中只有上一层或者说最后一层在调用位置中起作用。
	function foo() {
        console.log( this.a );
    }
    var obj2 = {
        a: 42,
        foo: foo
    };
    var obj1 = {
        a: 2,
        obj2: obj2
    };
    obj1.obj2.foo();  // 42

4.如果以上都不是的话,使用默认绑定。

如果在严格模式下,就绑定到 undefined,否则绑定到全局对象。
对于默认绑定来说,决定 this 绑定对象的并不是调用位置是否处于严格模式,而是函数体是否处于严格模式。如果函数体处于严格模式,this 会被绑定到 undefined,否则 this 会被绑定到全局对象。
关于全局对象:
浏览器环境下指向的是 window,node 环境下指向的是 module.exports。
	function foo() {
        console.log( this.a );
    }
    var a = 2;
    foo();  // 2
	// 函数体是严格模式,则不能将全局对象用于默认绑定,此时 this 会绑定到 undefined。
    function foo() {
        "use strict";
        console.log( this.a );
    }
    var a = 2;
    foo();  // Uncaught TypeError: Cannot read property 'a' of undefined
	// 函数体是非严格模式,this 默认绑定到全局对象 Window
	function foo() {
        console.log( this.a );
    }
    var a = 2;
    (function(){
        "use strict";
        foo();  // 2
    })();

5.箭头函数

箭头函数的 this 在声明的时候就决定了。

箭头函数本身是没有 this 和 arguments 的,在箭头函数中引用 this 实际上调用的是定义是的上一层作用域的 this。这里强调一下是上一层作用域,因此对象是不能形成独立的作用域的。

	var obj2 = {
		num: 10
	};
	var obj = {
        fn: () => {
            console.log(this);
        },
        fn2: function() {
            console.log(this);
        }
    }
    obj.fn.call(obj2);  // Window对象,因为箭头函数在定义的时候 this 就固定了,用 call 不能改变其指向
    obj.fn2.call(obj2);  // {num: 10},普通函数,this 指向 obj2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值