JavaScript的this(三)call,apply,bind,箭头函数

使用bind,apply,call改变函数中this的指向

首先先举个例子

var a = 20

function test(){
  console.log(this.a); // 20
}

test()

向上面这样直接执行函数,函数内部的this默认是指向全局的,在浏览器中这个this就指向window,所以this.a = 20

通过call,apply,bind方法可以改变函数内部this的指向

  • call , apply
var obj1 = {
  name: "obj1"
}

var obj2 = {
  name: "obj2"
}

var name = "全局的name"

function printName(a, b) {
  console.log(this.name, a, b);
}


printName.call(obj1, 1, 2) // obj1 1 2
printName.call(obj2, 3, 4) // obj2 3 4

printName.apply(obj1, [5, 6]) // obj1 5 6
printName.apply(obj2, [7, 8]) // obj2 7 8

call和apply的区别就在于传递参数的形式不同,第一个参数都是你想为函数指定的this,call的参数就直接以逗号隔开的方法直接写参数,而apply是以数组的形式进行传参

// call
function.call(thisArg, arg1, arg2, ......)

// apply
function.apply(thisArg, [arg1, arg2, ......])

两者的返回值都是调用call或者apply方法的函数的返回值结果,没有返回值那就是undefined

function test(){
  return "哈哈哈"
}

function test1(){
  return true
}

console.log(test.apply()); // 哈哈哈
console.log(test1.call()); // true

不过在指定this的时候,也可以指定是null或者undefined,不过只有在严格模式下才是真正将this指定为null或者undefined,非严格模式下,自动替换成全局对象

function test() {
  console.log(this);
}

test.call(null) // window
var a = "haha"

function test() {
  console.log(this.a); // haha
}

test.call(null)
  • bind 方法

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用 (mdn)

它的参数同call方法

function.bind(thisArg, arg1, arg2, ......)

不同的就是返回值了,bind调用后返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。

说白了,就是返回了一个新的函数,这个函数中才被绑定了你指定的this和参数,call和apply调用就执行了,bind需要手动调用返回的函数才行

var name = "全局的"
var obj = {
  name: "obj的"
}

function test(n, m) {
  console.log(this.name, n, m);
}

var newFn = test.bind(obj, 1, 4)

console.log(newFn);
// ƒ test(n, m) {
//   console.log(this.name, n, m);
// }

newFn() // obj的 1 4

注意:bind只能绑定一次,不能再给bind返回的函数再执行bind,结果始终是以第一次绑定为准

var name = "全局的"
var obj = {
  name: "obj的"
}

var obj2 = {
  name: "obj2的"
}

function test(n, m) {
  console.log(this.name, n, m);
}

var newFn = test.bind(obj, 1, 4)
newFn() // obj的 1 4

var newFn1 = newFn.bind(obj2, 2, 3)
newFn1() // obj的 1 4

this在箭头函数中的指向

箭头函数比较特殊,其内部并没有this绑定,它能访问到的this其实是
该函数所在的作用域指向的对象,所以大家要对作用域有所了解。箭头函数也不可以做构造函数

  • 全局下
var test = () => {
  console.log(this); // window
}

test()
function test() {
  var innerTest = () => {
    console.log(this); // window
   }

  innerTest()
}

test()
  • 对象
var name = "全局下的name"
var obj = {
  name: "obj的name",
  logName: function(){
     console.log(this.name); // obj的name
  },
  printName: () => {
    console.log(this.name); // 全局下的name
  }
}
obj.printName()

看到这个结果,部分同学们是不是有点小意外,箭头函数printName的this还是指向window,不是谁绑定他就指向谁。现在改一下:

    var name = "全局下的name"
    var obj = {
      name: "obj的name",
      outFn: function () {
        console.log(this);  // {name: 'obj的name', outFn: ƒ}
        var printName = () => {
          console.log(this.name); // obj的name
        }

        printName()
      }
    }

    obj.outFn()

此时箭头函数printName在普通函数outFn里面,outFn的作用域的this就是指向调用它的对象

  • 静态this指向
    var a = 1
    var obj = {
      a: 2
    }

    var test = () => {
      console.log(a);
    }

    test() // 1
    test.call(obj) // 1
    test.apply(obj) // 1
    test.bind(obj)() // 1

箭头函数里面的this就是指向其当前作用域指向的this,不接受通过call等方法进行this修改。

我觉得也可以这样理解,箭头函数它在找this的时候,从里向外找,找到非箭头函数的作用域

若理解有误,希望大家批评指正

你可能感兴趣的:(JavaScript的this(三)call,apply,bind,箭头函数)