美文网首页程序员
关于JS中函数内部this的指向

关于JS中函数内部this的指向

作者: 时光已翩然轻擦 | 来源:发表于2020-06-06 22:22 被阅读0次

版本记录:
1. 2020/06/04 初版
2. 2020/06/09 补充 “class静态方法中的this”,增加了一个关于setTimeout的栗子

一、this

  • this是JavaScript中的一个关键字,当一个函数被调用时,除了传入函数的显式参数以外,名为this的隐式参数也被传入了函数。
  • this参数指向了一个自动生成的内部对象,这个内部对象被称为函数上下文
  • JavaScript中的this依赖于函数的调用方式。

二、设计目的

  • 由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。
  • 所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。

三、this的指向

  • this的指向是在函数执行时确定的,即:调用函数的那个对象。

四、普通场景

1. 函数直接调用时(自然执行时)

this指向全局或undefined。

  • 自然执行:不被点出来/不被挂在对象上/不被访问控制符访问到。
  • 指向全局:非严格模式下,在node环境下为global,在浏览器环境下为window。
  • 指向undefined:严格模式下。
例1:
  function work(){
    console.log('this:', this)
  }
  work() // this 指向 全局
例2:
  var worker = {
    name: 'worker',
    work: function () {
      console.log('this:', this)
    }
  }
  var work = worker.work
  work() // this 指向 全局

2.函数被对象调用时

this指向点出它的那个对象

例1:
  var worker = {
    name: 'worker',
    work: function () {
      console.log('this:', this)
    }
  }
  worker.work() // this 指向 worker
例2:
  var worker = {
    name: 'worker',
    hand:{
      name:'hand',
      work: function () {
        console.log('this:', this)
      }
    }    
  }
  worker.hand.work() // this 指向 hand

  var workerWife = {}
  workerWife.work = worker.hand.work
  workerWife.work() // this 指向 workerWife

  var work = worker.hand.work
  work() // this 指向 全局

3.new一个实例时

new执行时this指向这个实例

例:
  function Person(name){
    this.name = name
    console.log(this)
  }

  var worker = new Person('workers') // this 指向 worker 这个实例

4.其他栗子

例1:
  window.addEventListener('click', worker.work) // this 指向 window
例2:
  (1,worker.work)() // this 指向 全局
*例3:
function Person () {
  this.buy = function () {
    console.log('this::', this)
  }
}
var teacher = new Person()
wife.buy = teacher.buy
wife.buy() // this指向wife

五、特殊场景

1.apply/call/bind时

this指向第一个参数

apply
  • 接收数组形式的参数
  • 立即执行
  function work(first, second){
    console.log('this', this, first, second)
  }
  var worker = { name: 'worker'}

  work.apply(worker, ['a', 'b']) // 会立即执行, this 指向 worker
call
  • 分别接收参数
  • 立即执行
  function work(first, second){
    console.log('this', this, first, second)
  }
  var worker = { name: 'worker'}

  work.call(worker, 'a', 'b') // 会立即执行, this 指向 worker
bind
  • 分别接收参数
  • 不立即执行,返回一个新函数(不会改变原函数),这个函数绑定了新对象
  function work(first, second){
    console.log('this', this, first, second)
  }
  var worker = { name: 'worker'}
  var workerWife = { name: 'workerWife'}

  var workerWork = work.bind(worker, 'a', 'b') // 不会立即执行
  workerWork() // this 指向 worker
  
  workerWife.workerWork = workerWork
  workerWife.workerWork() // this 依然指向 worker,不受前边点出它的对象影响

  // 也可以在bind的时候不传参,执行的时候传
  var workerWork = work.bind(worker) // 不会立即执行
  workerWork('a', 'b') // this 指向 worker
对比
  eat.call(dog, a, b) = eat.apply(dog, [a, b]) = (eat.bind(dog, a, b))() = dog.eat(a,b)

2.箭头函数时

箭头函数的this指向:箭头函数定义时 离箭头函数最近的 非箭头函数的 执行上下文 的this。

例1:
  function outer(){
    console.log('outer this', this)

    const work = () => {
      console.log('work this', this)
    }
    work()
  }

  var worker = {
    name: 'worker'
  }

  worker.outer = outer
  worker.outer() // outer this 和 work this 都指向 worker
例2:
  function outer(){
    console.log('outer this', this)

    const work = () => {
      console.log('work this', this)
    }

    function inner(){
      console.log('inner this', this)
      work()
    }
    inner()
  }

  var worker = {
    name: 'worker'
  }

  worker.outer = outer
  worker.outer() // outer this -> worker,  inner this -> 全局, work this -> worker

3.组合栗子

例1:
  const work = () => {
    console.log('this', this)
  }

  var worker = {
    name: 'worker'
  }

  work.call(worker) // this 指向 全局
例2:
function a() {
  setTimeout(() => {
      console.log('this1::',this)
  }, 1000)
  setTimeout(function () {
      console.log('this2::',this)
  }, 1000)
}
var b = {name:'张三'}
a.apply(b) // this1指向b,this2指向全局

4.class静态方法中的this

class静态方法中的this指向类,而不是实例。

静态方法
  • 类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

  • 如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。

例:
class Person{
  static eat(){
    console.log('this',this)
  }
}
Person.eat() // this指向Person

六、参考资料

相关文章

  • 关于JS中函数内部this的指向

    版本记录:1. 2020/06/04 初版2. 2020/06/09 补充 “class静态方法中的this”,增...

  • 关于js函数中this的指向的问题

    @(javascript)[JavaScript中this的指向] 关于js函数中this的指向的问题 javas...

  • JS中this的指向

    什么是this? 它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。 JS中this的指向,取...

  • es6(class)

    js中的私有方法 _privateMethod(){}形式 关于this 函数中的this指向函数的调用者unde...

  • 关于 JS 函数中的 this 指向

    函数中的 this 如果不系统的深入的去学习,总会让人感到困惑。它的字面意思往往给人一种就是指向函数自身的感觉,事...

  • 关于 JS 函数中的 this 指向

    函数中的 this 如果不系统的深入的去学习,总会让人感到困惑。它的字面意思往往给人一种就是指向函数自身的感觉,事...

  • this指针

    (1)普通函数中的this指向:this指向普通函数中的调用者; 通过call和apply改变函数内部this的指向:

  • 前端面试题(持续补充)

    js,node.js基础: 闭包 闭包是能够读取其他函数内部变量的函数。在js中,只有函数内部的子函数可以访问内部...

  • this

    this在js中主要研究的是函数中的this,不代表函数外没有this,函数外的this指向window js中的...

  • Javascript中的this

    关于this 在JS中,this总是指向一个对象。this的指向是在运行函数时动态绑定的。 使用this的四种情况...

网友评论

    本文标题:关于JS中函数内部this的指向

    本文链接:https://www.haomeiwen.com/subject/oufzzhtx.html