JavaScript中this的指向和call, apply,bind

116 阅读3分钟

this的指向问题对于刚刚接触JavaScript的人来说确实是比较疑惑的,一是因为它的不确定性,二是对JavaScript没有进行深入的了解,对于语法和执行过程不太了解,下面具体来看一下编写JavaScript的过程中this的指向具体由什么确定

说到this,一般指的都是函数调用中this的指向,this的指向是在函数被调用时才确定的,一般可以分为如下几类:

隐式指向

显示指向,this永远都是指向最后调用它的那个对象,对这句话的理解至关重要,下面将会阐明 new构造函数 call和apply 隐式指向

说到隐式指向,一般是指函数被直接调用(而不是通过某一个对象),此时函数内部的this指向window

<script>
    let a = 'hello'
  function A() {
    let a = 'hi'
    console.log(this) // window
    console.log(this.a) // hello
  }
</script>

注意:在严格模式下,全局调用时,函数内部的this指向的是undefined

显示指向

显示指向,一般是指函数通过一个对象被调用,此时函数中的this指向那个对象,简单来说就是谁调用就指向谁

let obj = {
  a: 'hello',
  show: function() {
    consoel.log(this.a)
  }
}
obj.show() // hello

还有一种多级调用的情况

var obj = {
  a: 'hello',
  b: {
    a: 'hi',
    show: function() {
      console.log(this.a) // hi
    }
  }
}
obj.b.show() // hi  show最后是被b对象调用,this指向b,b中有a属性,所以返回hi
var fun = a.b.show
fun() // undefined 等同于 window.fun() 所以this指向window 而window中没有申明a变量

this永远都是指向最后那个调用他的对象,此时这个概念就变得尤为重要

new构造函数

JavaScript中函数分为普通函数和构造函数,其实他们都是一样的,只不过被调用的方式不一样, 构造函数通过new被调用,首字母大写

function Person(name, age, sex) {
  this.name = name
  this.age = age
  this.sex = sex
  this.showName = function() {
    return this.name
  }
}
const person = new Person('zhangli', 30, '男')
person.name // zhangli

构造函数中的this指向实例化的对象,可以参考new构造函数的过程,

call和apply

call和apply是函数上的静态方法,可以用来改变函数内部this的指向

var obj = {
  title: 'hello',
  showTitle: function() {
    return this.title
  }
}
obj.showTitle() // hello
obj.showTitle.call({title: 'hi'}) // 此时showTitle内部的this就指向{title: 'hi'}
obj.showTitle.apply({title: 'hi'})

call和app的功能相同,只不过传递的参数有所不同

obj.fun.call({}, a,b,c) // call以单个参数分别传递
obj.fun.apply({},[a,b,c]) // apply已数组的形式传递
bind

bind方法会创建一个新函数,当这个新函数被调用时,它的this值是传递给bind()的第一个参数

fun.bind(thisArg, arg1[, arg2[,...]]]) thisArg: 当绑定的函数被调用时,该参数会作为原函数运行时的this指向,当使用new操作符调用绑定函数时,该参数无效 参数:参数是可以选的,当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数

function test(a,b,c) {
 return this + a + b + c
}
const _test = test.bind(1, 2) // 第一个参数为绑定函数的this, 第二个参数为绑定函数的第一个参数
_test(3,4) // 这两个参数依次为被绑定函数的第二个和第三个参数