this关键字

117 阅读2分钟

千里之行,始于足下。 ——— 《老子》

全局中的this

    console.log(this)

在全局状态中的this指向window。

函数中的this

    function fn() {
        console.log(this)
    }
    fn()

函数中的this,fn()实际相当于window.fn(), 所以函数里的this指向调用这个函数的对象,window。

对象中的this

    let cat = {
        name: '毛球',
        sayName () {
            console.log( 'my name is' + this.name)
        }
    }
    cat.sayName()

方法中的this,指向调用方法的对象,所以这里的this指向cat对象。

构造函数中的this

    function Fn() {
        this.name = 'benjamin'
    }
    let fn = new Fn()
    console.log(fn)

new 关键字发挥了作用,会将构造函数中的this指向创建出来的对象,所以此处之行fn方法时,this指向fn。

计时器中的this

    let cat = {
        name: '毛球',
        sayName () {
            setTimeout(function() {
                console.log(this)
            }, 1000)
        }
    }
    cat.sayName()

实际打印的this实则指向window,因为setTimeout是window对象调用的。

箭头函数中的this

    let cat = {
        name: '毛球',
        sayName () {
            setTimeout(() => {
                console.log(this)
            }, 1000)
        }
    }
    cat.sayName()

将定时器的普通函数改成箭头函数后,this指向cat对象,可以这样理解:

  1. 普通函数中的this,谁调用this就指向谁。箭头函数的this,在哪里定义,就指向哪里。
  2. 箭头函数外指向谁,那this就是指向谁。
  3. 箭头函数没有this。

call,apply,bind

call

    funtion fn() {
        console.log('hello world')
    }
    fn.call()

由此可见,call可以调用函数,call还可以改变函数中this的指向。

    funtion fn() {
        console.log(this.name)
    }
    let cat = {
        name: '毛球'
    }
    fn.call(cat)

原本fn和cat并没有联系,但是通过call,能够将fn中的this,指向cat,上面结果打印 "毛球"。

apply

apply的使用方法和call类似,区别在于传参的方式。

    fn.call(cat, '鱼', '肉')
    
    fn.apply(cat, ['鱼', '肉'])

bind

bind传参方式和call一模一样。区别在于bind不会执行函数。

    fn.call(cat, '鱼', '肉')
    
    fn.bind(cat, '鱼', '肉') // 不会有打印结果
    
    let fun = fn.bind(cat, '鱼', '肉')
    fun() // bind调用的返回值,再去触发执行

call, apply, bind的应用-实现继承

    function Animal() {
        this.eat = function() {
            console.log('eat something')
        } 
    }
    
    function Cat() {
        Animal.call(this)
    }
    let cat = new Cat()
    cat.eat()

分析:

  1. 小cat本没有eat方法,但是构造函数里掉用了call
  2. Cat构造函数里this指向小cat
  3. 所以Animal的this指向了小cat
  4. 小cat也就有eat方法了

后面会再总结new关键字,call,apply,bind的源码实现。