zoukankan      html  css  js  c++  java
  • 摸清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,?,?,?

    案例五: 待补充

  • 相关阅读:
    E4A易安卓3.6无需注册编译Release
    PHP中几种常用的网页跳转代码
    超详细教你重新封装GHO(ndeer和绿茶)教程
    程序员和编码员之间的区别
    迅闪三层下载游戏无速度
    POST注册DZ论坛或发帖
    解决局域网文件共享设置
    妻子 情人 红颜知己
    照片与同行元素居中的方法
    【转】SVN使用教程总结
  • 原文地址:https://www.cnblogs.com/Tiboo/p/11370325.html
Copyright © 2011-2022 走看看