美文网首页
深入之从this

深入之从this

作者: 明里人 | 来源:发表于2019-07-13 17:31 被阅读0次

    当JavaScript代码执行一段可执行代码时,会创建对应的执行上下文。
    对于每个执行上下文,都有三个重要属性

    • 变量对象
    • 作用域链
    • this
    this 是什么

    this既不指向函数自身,也不指向函数的词法作用域。它实际是在函数被调用时才发生的绑定,this具体指向什么,取决于你是怎样调用的函数。

    this 的四种绑定规则
    • 默认绑定
    • 隐式绑定
    • 显示绑定
    • new 绑定
    • 箭头函数
    默认绑定
    function foo(){
      console.log(this.a);
    }
    var a = 2;
    foo(); 
    

    打印结果为2.
    因为foo()是直接在全局调用的,进行了默认绑定,this指向了window。

    注意:在严格模式下,全局对象将无法使用默认绑定,执行会保undefined错误

    function foo(){
        'use strict';
        console.log(this.a);
    }
    var a = 2;
    foo();
    // TypeError: Cannot read property 'a' of undefined
    
    隐式绑定

    有时候,函数的调用是在某个对象上触发的

    function foo() {
      console.log(this.a);
    }
    var a = 2;
    var obj = {
      a: 3,
      foo: foo
    };
    obj.foo();
    

    obj.foo 打印结果是3,foo通过obj调用,此时this指向obj对象,访问obj的属性a。如果obj没有属性a,也不会向上访问全局的a,此时打印为undefined。

    多层调用链
    function foo(){
        console.log(this.a);
    }
    var a = 2;
    var obj1 = {
        a: 4,
        foo: foo
    };
    var obj2 = {
        a: 3,
        obj1: obj1
    };
    obj2.obj1.foo();
    

    obj2.obj1.foo 打印结果为4。
    这里调用链不只一层,存在obj1、obj2两个对象,但foo中的this会指向最近一次的调用者 ---- obj1。

    隐式丢失(函数别名)
    function foo(){
        console.log(this.a);
    }
    var a = 2;
    var obj = {
        a: 3,
        foo: foo
    };
    var bar = obj.foo;
    bar();
    

    打印结果是2。尽管obj隐式绑定了foo,但将其赋值给bar,而bar在全局调用,所以访问全局的a。

    显式绑定

    通过call() 、apply()、bind()来实现。

    function foo(){
        console.log(this.a);
    }
    var a = 2;
    var obj1 = {
        a: 3
    }
    var obj2 = {
        a: 4
    }
    foo.call(obj1);
    foo.apply(obj2);
    foo.bind(obj1)();
    

    打印结果是3,4。
    因为这里显式的申明了要绑定的对象,所以this就被绑定到了obj1和obj2

    new 绑定

    如果函数没有返回其他对象,那么函数中的this指向new 返回的这个对象。

    function Foo(a){
      this.a = a;
    }
    var a = 2;
    var bar1 = new Foo(3);
    console.log(bar1.a);  // 3
    var bar2 = new Foo(4);
    console.log(bar2.a);  // 4
    
    箭头函数

    箭头函数本身不存在this,this指向上一级对象
    看一个例子

    function Person(){
        this.age = 0;
        setTimeout(function(){
            this.age ++;
            console.log(this,this.age);  // this指向window
        },1000)
    }
    let person = new Person();
    

    如果我们想在计时器中访问Person的成员属性,通常会这样做

    function Person(){
        this.age = 0;
        let self = this;
        setTimeout(function(){
            self.age ++;
            console.log(self,self.age);  // this指向Person
        },1000)
    }
    let person = new Person();
    

    使用箭头函数可以达到这样效果,将this指向上一级对象

    function Person(){
        this.age = 0;
        setTimeout(() => {
            this.age ++;
            console.log(this,this.age);  // this指向Person
        },1000)
    }
    let person = new Person();
    

    相关文章

      网友评论

          本文标题:深入之从this

          本文链接:https://www.haomeiwen.com/subject/bccmkctx.html