[Js] this 指向

目录

  • 1.默认绑定
  • 2.隐式绑定
  • 3.显示绑定
  • 4. new 绑定 - 箭头函数

引入this的初衷就是想在原型继承的情况下,拿到函数的调用者
this 指向的四种绑定方式是:默认绑定、隐式绑定、显示绑定、new 绑定四种

1.默认绑定

(1)在全局环境下 this 指向 window
(2)在函数独立调用的时候,this 指向 window;
(3)被嵌套的函数独立调用时,this 默认绑定到 window
(3)自执行函数,this 指向 window
(4)闭包中,this 默认指向 window

解释:
(1)因为全局变量和全局函数,都是挂载到 window 对象下的,打印 this 相当于用 window. 的方式调用
(2)独立调用, 就是函数调用模式 是 函数名(参数){}, 不加任何其他的东西, 像对象 o.fuc() 就不是;
(4)闭包中的 this 重定向:由于闭包的 this 默认绑定到 window 对象,但又常常需要访问嵌套函数的 this,所以常常在嵌套函数中使用 var that = this,然后在闭包中使用 that 替代 this,使用作用域查找的方法来找到嵌套函数的 this 值


2.隐式绑定

(1)被直接对象所包含的函数调用时,也称为方法调用,this 隐式绑定到该直接对象

隐式丢失
隐式丢失就是,之前隐式绑定不是 直接绑到调用它的直接对象上嘛,但这个对象又发生改变了,丢失了绑定对象,this 就又默认绑定到 window 上
(1) 为函数调用创建别名; 比如函数又被赋值到另一个变量上,这个变量跟这个函数的 this 没有关系,就会指向 window

function foo(){
     
  console.log(this.a);
}
var obj={
     
   a:2,
   foo:foo
}
var bar=obj.foo;
var a="window";
bar()//window

(2)传入回调函数; 把函数当做参数传递到另一个函数中,也会发生隐式丢失的情况,父函数可以决定子函数的 this 指向

function foo(){
     
   console.log(this.a);
}
function doFoo(fn){
     
   fn();
}
var obj={
     
   a:2,
   foo:foo
}
var a="window";
doFoo(obj.foo)//window

(3)内置函数 setInterval 和 setTimeout,内部第一个参数的回调函数默认指向 window,因为这两个方法是 window 的方法

function setTimeout(fn,delay){
     
   //等待delay毫秒
   fn();
}

3.显示绑定

显示绑定就是用 call, apply, bind 方法用来改变 函数体内部的 this 指向

< 不同之处 >
它们在功能上是没有区别的,都是改变 this 的指向;

  • callapply 方法都是在调用之后立即执行。而 bind 调用之后是返回原函数,需要再调用一次才执行
  • 传递参数上不同,第二个参数,callbind 方法都是直接传入参数,而 apply 是以数组的形式传入;
<body>
  <script>
    var obj = {
     
      name: '静静',
      objAge: this.age,
      myFun: function () {
     
        console.log(this.name + '年龄 ' + this.age);
      }
    }
    var db = {
     
      name: '小张',
      age: 99
    }
    // 输出都是 "小张的年龄 99", 可以看到调用 obj.myFun 时其中的 this 本来应该指向 obj
    // 我们通过 call, apply, bind 将 this 改向了 db, 就能获得 db 中的值了;
    obj.myFun.call(db);
    obj.myFun.apply(db);
    obj.myFun.bind(db)();
  </script>
</body>

我们再查对比一下它们的传参情况:
<body>
  <script>
    var obj = {
     
      name: '小颖',
      objAge: this.age,
      myFun: function (from, to) {
     
        // 下面都打印: 小张年龄99, 来自成都, 去往上海
        console.log(this.name + '年龄' + this.age + ', 来自' + from + ', 去往' + to);
      }
    }
    var db = {
     
      name: '小张',
      age: 99
    }
    obj.myFun.call(db, '成都', '上海');
    obj.myFun.apply(db, ['成都', '上海']);
    obj.myFun.bind(db, '成都', '上海')();
  </script>
</body>

< 实际应用 >

  • call 方法可以用来代替另一个对象调用一个方法(本身无该方法,才选择调用)。call 方法可以将一个函数的上下文从初始的对象转成 你指向的新对象;
    ① 使用 call 方法可以判断数据类型 Object.prototype.toString.call()
    ② 求数组的最值 Math.max.apply(null, arr); 和最小值 Math.min.apply(null, arr);
  <script>
    let arr = [10, 52, 6, 80];
    let maxNum = Math.max.apply(null, arr);
    console.log(maxNum); // 80
  </script>

4. new 绑定 - 箭头函数

(1)new 构造函数中的 this 指向的是当前实例化的对象;

<script>
  function Person(name, age) {
     
    this.name = name;
    this.age = age;
    console.log(this); // Person {name: "Tom", age: 18}
  }
  var v1 = new Person('Tom', 18);
</script>

(2)箭头函数的 this 指向
箭头函数没有自己的 this, 它的 this 是继承而来的,是源于外层代码块中的 this,箭头函数的 this 是在定义函数时绑定的,函数在定义的时候,this 就继承了定义函数的对象;


箭头函数和普通函数的区别?

  • 箭头函数使用箭头定义,普通函数中没有
  • 普通函数可以有匿名函数,也可以有具体名函数,但是箭头函数都是匿名函数。
  • 箭头函数不能用于构造函数,不能使用 new 创建实例
  • 在普通函数中,this 总是指向调用它的对象,箭头函数本身没有 this,会借用外层的 this 使用

你可能感兴趣的:(JavaScript,javascript)