this指向与绑定规则

我心飞翔 分类:javascript

this对象是在运行时基于函数的执行环境绑定的,也就是说,this 是和执行上下文绑定的。如果函数没有调用,那么this指向就没有确定下来。

以下总结常见的this五种绑定规则,让你从绑定规则深刻理解this的指向~~

一、默认绑定方式

this默认绑定指向window对象,直接上代码来看:

// 1、默认绑定规则:this默认指向window
function foo() {
        console.log(this === window)
    }
foo()  //打印出true
 

从这里可以看出,如果是一个全局函数,默认是绑定指向window对象的。

二、隐式绑定规则:谁调用就指向谁

函数被作为某个对象的方法被调用时,this指向那个对象。

    // 2、隐式绑定规则:谁调用就指向谁
    var obj = {
        foo: function() {
            console.log(this) // this指向obj 
        }
    }
    obj.foo() // 对象的方法
 

此处还涉及到一个隐式丢失的概念。

什么是隐式丢失呢,顾名思义,隐式绑定规则无效了,也就是隐式绑定的函数丢失绑定对象,从而默认绑定到全局或者udnefinded.

我们分为四种情况来看隐式丢失。

1、第一种情况:为函数调用创建别名, 即创建变量放置结果

    function foo() {
        console.log(this.a)
    }
    var obj = {
        a: 2,
        foo: foo
    }
 
    var bar = obj.foo;  // 创建别名
    var a = 1;
    bar() // 打印出1,即this指向window
 

2、第二种情况:传入回调函数,函数作为参数传递,也就是常说的隐式赋值

    function foo() {
        console.log(this.a)
    }
 
    function doFoo(fn) { // fn作为参数传递
        fn();   
    }
    var obj = {
        a: 2,
        foo: foo
    }
    var a = 1
    doFoo(obj.foo) // 打印出1,即this指向window
 

3、第三种情况:出现在内置函数中,比如setTimeout这些

  function foo() {
        console.log(this.a)
    }
    var obj = {
        a: 2,
        foo: foo
    }
    var a = 1
    setTimeout(obj.foo, 100) // 打印出1,即this指向window
 

4、第四种情况:函数的赋值

    function foo() {
        console.log(this.a)
    }
    var obj = {
        a: 2,
        foo: foo
    }
    var obj2 = {
        a: 3
    }
    var a = 1;
    (obj2.foo = obj.foo)(); //打印出1,即this指向window
 

三、显式绑定规则:call、apply、bind

显式绑定规则,为什么叫显式呢,我自己理解的话认为是因为通过这三个函数传入的参数就是绑定的对象,所以看起来比较明显hhhhh

    // 3、显式绑定规则
    var obj = {
        a: 2,
        foo() {
            console.log(this.a)
        }
    }
 
    var obj2 = {
        a: 3
    }
 
    obj.foo.call(obj2) // 打印出3,this指向obj2  obj.foo.call(obj2,1,2)  传参方式:列出参数
    obj.foo.apply(obj2) // 打印出3,this指向obj2  obj.foo.apply(obj2,[1,2]) 传参方式:传数组
    var fn = obj.foo.bind(obj2)
    fn() // 打印出3,this指向obj2
 

这里涉及到手写call、apply、bind的方法,我认为手写这几个方法可以让自己对this指向理解的更加深刻,而不是直接调用那么傻瓜式!!

四、new绑定

    // 4、new绑定规则
    function foo() {
        console.log(this)
    }
    foo() // 默认指向window
    new foo() // 指向foo这个new出来的对象
 

五、箭头函数

     // 4、箭头函数
    var name = "1"
    const obj = {
        name: 2,
        foo: () => {
            console.log(this) // 指向window,指向外部函数,也就是window
            console.log(this.name) // 打印出1
        }
    }
    obj.foo()
 

这五种规则其实都不难理解,认真的动手实践一遍就能理解啦。另外,这里的代码都是分开规则讲的,有没有想过,如果一段代码里面用到了多种规则,那如何判定呢?

其实规则是有优先级的:箭头函数 > new > 显式 > 隐式 > 默认绑定

听别人说千遍万遍都不如自己动手一遍,具体的还需要自己进行实践并理解。

回复

我来回复
  • 暂无回复内容