摸清this指向是一条漫长的路

默认绑定:

var name = 'Tiboo'
function sayHi(){
  console.log(this)                  // Window对象
} 
sayHi(); // sayHi运行在全局环境

隐式绑定:

函数的调用是在某个对象上触发的,即调用位置上存在上下文对象
    var name = 'yangfu'
    function sayHi() {
        console.log(this)    // 指向testMan这个对象
        console.log('hello', this.name)   // hello, Tiboo     
    }
    var testMan = {
        name: 'Tiboo',
        sayHi: sayHi
    }
    testMan.sayHi()   
    // 对象属性链中只有最后一层影响到调用位置

var name = 'yangfu' function sayHi() { console.log('hello', this.name) } var testMan1 = { name: 'Tiboo1', man: testMan2 } var testMan2 = { name: 'Tiboo2', sayHi: sayHi }
    testMan1.man.sayHi()
console.log(testMan1.man) // hello, Tiboo2

绑定丢失:

   function sayHi() {
        console.log(this)  // 指向Window对象
        console.log('hello,', this.name)  // hello, yangfu
    }
    var testMan = {
        name: 'Tiboo',
        sayHi: sayHi
    }
    // 此时man直接指向了sayHi, 和testMan没啥关系
    var man = testMan.sayHi
    var name = "yangfu"
    man()
 
显示绑定:
   function sayHi(){
        console.log('Hello,', this.name);  // Hello, Tiboo
    }
    var testMan = {
        name: 'Tiboo',
        sayHi: sayHi
    }
    var name = 'yangfu'
    var man = testMan.sayHi
    // 通过apply, 设置函数体内this指向的值,此时指向了testMan
    man.apply(testMan)
 
将null或者是undefined作为this的绑定对象传入call、apply( 指向被忽略,实际应用的是默认绑定规则,默认绑定其实没研究透,待补充)

 function sayHi(){
  console.log('Hello,', this.name); // Hello, yangfu
 }
 var testMan = {
  name: 'Tiboo',
  sayHi: sayHi
 }
 var name = 'yangfu'
 testMan.sayHi.call(null)

new绑定:

    var name = 'Tiboo'
    function sayHi(name){
       this.name = name;
    }
    var man = new sayHi('Tiboo2')
    console.log(man.name) // Tiboo2

箭头函数:

  • 没有自己的this, 继承外层代码的this
  • 无法用call()、apply()、bind()这些方法去改变this的指向
  没有使用箭头函数:
  var obj = {
    hi: function(){
        console.log(this);
        return function() {
          console.log(this)
        }
    }
  }  
  let hi = obj.hi();  //输出obj对象
  hi();               //window对象

使用箭头函数后:
    var obj = {
      hi: function(){
        console.log(this);
        return () => {
          console.log(this)
        }
       }
    }
    let hi = obj.hi(); //输出obj对象
    hi(); //输出obj对象

自执行函数:

  • 自执行函数里面的this指向window
 var obj = {
    hi: function(){
        console.log(this); // 输出obj对象
        (function() {
          console.log(this) // window对象
        })()
    }
  }  
  let hi = obj.hi();  

基本上关于this的指向就那么多了,下面是我收集的一些关于this的面试题或者自认为比较有趣的题,孰能生巧,复杂的事情都是由最简单的事情拼接而来的,so,只要肯花心思,问题便不再是问题。

案例一:

  var a = {
    name: 'A',
    fun: function() {
      console.log(this.name);
    }
  };
  a.fun();  // 对象调用, this指向a, this.name = 'A'
  a.fun.call({ name: 'B' }); // 使用call改变作用域,this指向新创建对象, this.name = 'B'
  var fun1 = a.fun; // 将对象方法赋值给一个全局变量
  fun1(); // this指向全局, 为空

案例二:

var number = 5;
  var obj = {
      number: 3,
      fn: (function () {
          var number;
          this.number *= 2;
          number = number * 2;
          number = 3;
          return function () {
              var num = this.number;
              this.number *= 2;
              console.log(num);
              number *= 3;
              console.log(number);
          }
      })()
  }
  var myFun = obj.fn; // 自执行, this.number(window) = 10
  myFun.call(null);  // this指向window, 传入null导致默认绑定,this.number(window) = 20; num = 10; number = 9;
  obj.fn(); // this指向obj, num = 3; 闭包导致上次number值为9存在于内存中, number = 27
  console.log(window.number); // 20

案例三:

笔试题遇到的,当时只觉得头都绕大了,开始没看清,就想a都没定义,不会报错么

  var fn = (function(a) {
    this.a = a;
    return function(a) {
      a += this.a;
      console.log(a)
    }
  }(function(a, b) {
    return a
  }(3, 4)))
  fn(7)

解题步骤:

// 简化:
  (function(a, b) {
    return a
  }(3, 4)) // 运行得到结果3

  // 那么,上面function化简
  var fn = (function(a) {
    this.a = a;
    return function(a) {
      a += this.a;
      console.log(a)
    }
  }(3)) // 自执行函数this指向window,传入参数3后, this.a(window) = 3;
  fn(7) // fn()运行是闭包,此时this指向window, a = a + this.a = 3 + 7 = 10

案例四: 

题目来源:https://www.cnblogs.com/xxcanghai/p/4991870.html

function fun(n,o) {
  console.log(o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?
var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?

案例五: 待补充

原文地址:https://www.cnblogs.com/Tiboo/p/11370325.html