zoukankan      html  css  js  c++  java
  • this到底指向哪里

    this指向调用它的对象

    首先要明确,this指向调用方,谁调用,this指向谁。

    直接调用

    举个栗子:

    var 
        test = 'window'
    ;
    function testThis () {
        var test = 'inner';
        this.test = 'test change';
        console.log(this.test)
    }
    testThis(); // test change
    console.log(window.test) // test change
    

    在chrome中执行后可以发现,外部挂在window下的test被修改了,因为这个testThis的函数,是被window调用的,它只会读取window下的test。

    构造函数调用

    再举个栗子:

    var 
        test = 'window'
    ;
    function testThis () {
        var test = 'inner';
        console.log(this.test)
        this.test = 'test change';
        console.log(this.test)
    }
    var newTestThis = new testThis(); 
    // undefined
    // test change
    console.log(window.test) // window
    

    在chrome中执行以下可以发现,依次输出undefined、test change、window。
    这个栗子与上面的区别在于调用了new。此时,该函数作为构造函数调用,我们都知道,构造函数中的this都指向new出来的对象。所以this指向了这个新生成的newTestThis。自然地,window下test就没有被修改。

    嵌套调用

    接下来举一个栗子,来说明在函数嵌套调用时的this指向:

    var x = 'global'
    function testThis () {
    	// this.x = 'fuck';
    	// console.log(this)
    	console.log(this.x)
    }
    function innerObj () {
    	this.x = 'inner';
    	testThis();
    	this.innerTestThis = testThis;
    	this.innerTestThis();
    }
    
    function wrapObj () {
    	this.x = 'wrap';
    	// var test = new testThis();
    	// console.log(test.x)
    	testThis();
    
    	this.wrapTestThis = testThis;
    	this.wrapTestThis();
    
    	this.innerTestThis = new innerObj();
    }
    var wrap = new wrapObj();
    wrapObj();
    // global
    // wrap
    // global
    // inner
    // wrap
    // wrap
    // wrap
    // inner
    

    很明显,在函数嵌套时,如果不给函数指定调用对象,则不论被调用函数是在哪个函数的作用域里,被调用的函数的this都是指向window的。
    我们可以这样理解,在直接调用时,这些函数除了拥有自己的作用域外,就像是把这几行代码写到了相应的位置。可以想一下,所有的js代码最后都拼到一起,很明显,他们的调用方都是window。

    总结一下:1.不论函数在哪里被调用,只要没有指定调用方,则this都指向window。指定了调用方,就指向调用方。2.作为构造函数中调用,this指向新生成的对象。

    分析一下:setTimeout和setInterval

    bind的作用就是给函数一个指定的thisArg,经常使用bind的地方就是setTimeout和setInterval了。为什么呢?
    setTimeout和setInterval都有一个特点,它会将回调函数的作用域转移到window上面。其实结合我们上面说的,很容易知道为什么。
    以setTimeout为例:翻看MDN下setTimeout的定义,可以发现,setTimeout是把一段callback代码延迟执行。写过callback的同学都知道,callback的代码其实就是占了位,然后去调用一行行的代码,所以,callback中的this也会指向window。
    实际开发中,我们不希望this指向window,故而常使用bind来使this指向我们希望的对象。

    bind、apply、call

    说到了bind,就还需要提一下另外的可以改变this指向的方法:apply和call。
    这两个函数大同小异,只是传参有区别。不论使用apply还是call,都会传入一个thisArg,作为函数调用方,让函数中的this指向thisArg。
    在下一篇,我会介绍一下apply和call。

  • 相关阅读:
    [BZOJ3513] idiots
    2020牛客暑期多校训练营(第六场)A
    2020牛客暑期多校训练营(第六场)J
    2020牛客暑期多校训练营(第六场)H
    2020牛客暑期多校训练营(第六场)G
    2020牛客暑期多校训练营(第六场)K
    组队训练日志 2020.10.05
    Java基础
    Auditd
    Snort记录
  • 原文地址:https://www.cnblogs.com/liuyongjia/p/7661382.html
Copyright © 2011-2022 走看看