JS中各this的指向

我心飞翔 分类:javascript

全局环境

无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象window。

	console.log(this === window); // true
 

可以使用 globalThis 获取全局对象,无论你的代码是否在当前上下文运行。

函数(运行内)环境

在函数内部,this的值取决于函数被调用的方式。

简单调用

下面的代码不在严格模式下,且 this 的值不是由该调用设置的,所以 this 的值默认指向全局对象。

    function f1(){
      return this;
    }

    f1() === window;   // true
 

严格模式

在严格模式下,this将保持他进入执行环境时的值,所以下面的this将会默认为undefined

    function f2(){
      "use strict"; // 这里是严格模式
      return this;
    }

    f2() === undefined; // true
 

所以,在严格模式下,如果 this 没有被执行环境(execution context)定义,那它将保持为 undefined

如果想在严格模式下返回 window 对象,需要通过作为对象的属性或方法调用该函数,即 window.f2()

改变 this 指向

改变 this 的值,用 call 或者apply 方法。

    // 将一个对象作为call和apply的第一个参数,this会被绑定到这个对象。
    var obj = {a: 'Custom'};

    // 这个属性是在global对象定义的。
    var a = 'Global';

    function whatsThis(arg) {
      return this.a;  // this的值取决于函数的调用方式
    }

    whatsThis();          // 'Global'
    whatsThis.call(obj);  // 'Custom'
    whatsThis.apply(obj); // 'Custom'
 

call apply区别 :后面传的参数形式不同

  • call 需要把实参按照形参的个数传进去

  • apply 需要传一个 argument (数组)

        Person.call(this, name, age);
    
        person.apply(this, [name, age]);
     

对象的方法

当函数作为对象里的方法被调用时,它们的 this 是调用该函数的对象。

    var obj1 = {
        name : "obj1",
        fn1: function() {
            return this;
        }
    };

    console.log(obj1.fn1()); // obj1
 

this指向与方法定义的位置无关,只与最靠近的引用有关

    var obj = {};

    function independent() {
      return this;
    }

    obj.fn = independent;

    console.log( obj.fn() ); // obj
 

构造函数

当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。

    function Fn(){
        this.a = 100;
    }

    var obj1 = new Fn();

    console.log(obj1.a); // 100
 

构造函数里有 return

    function Fn1() {  
        this.user = 'gg';  
        return {};  // return 一个空对象
    }
    var obj1 = new Fn1;

    console.log(obj1.user); // undefined

//-------------------------------------------------------------

    function Fn2() {  
        this.user = 'gg';  
        return 1;  // return 一个数值
    }

    var obj2 = new Fn2;  

    console.log(obj2.user); //gg

//-------------------------------------------------------------

    function Fn3() {  
        this.user = 'gg';  
        return {user: 'mm'};  // return 一个对象
    }

    var obj3 = new Fn3;  

    console.log(obj3.user); //mm
 

如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

作为一个DOM事件处理函数

当函数被用作事件处理函数时,它的this指向触发事件的元素

箭头函数

阮一峰es6 : 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

    var foo = ()=>this;     // 全局定义箭头函数
    console.log(foo());     // window

    //  对象中箭头函数--------------------------------------------- this 定义的环境
    var obj1 = {foo};
    console.log(obj1.foo());     // window

    //  对象中普通函数--------------------------------------------- this 执行的环境
    var obj2 = {
        name : "obj2",
        foo : function(){
            return this;
        }
    }
    console.log(obj2.foo());    // obj2
 

如果理解成箭头函数的 this指向定义时所处的对象,那么下面的例子就会理解错误

    var obj3 = {
        name : "obj3",
        foo : ()=>this,

        obj4 : {
            name : "obj4",
            foo : ()=>this
        }
    }
    console.log(obj3.foo());    // window
    console.log(obj3.obj4.foo());    // window
 

箭头函数里面根本没有自己的this,而是引用外层的this

Nicholas C.Zakes的深入理解es6 :

如果箭头函数被非箭头函数包含,则this绑定指向的是最近一层非箭头函数的this;否则,this的值会被设置为全局对象

箭头函数的this 等同于上一层非箭头函数this值或者全局对象

    var obj5 = {
        name : "obj5",

        fn1 : function(){
            console.log(this);

            var fn2 = ()=>this;
            return fn2();
        }
    }

    console.log(obj5.fn1()); // obj5  obj5
 
	function foo() {
        console.log(this);  
        return () => {
            console.log(this);
            return () => {
                console.log(this);
                return () => {
                    console.log(this);
                };
            };
        };
    }

    var obj6 = {
        name :"obj6",
        foo
    }

    obj6.foo()()()(); // obj6 obj6 obj6 obj6
 

call() apply() bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响。

作者:掘金- JS中各this的指向

回复

我来回复
  • 暂无回复内容