什么是this

this不是编写时绑定,是运行时绑定。即没调用函数之前无法确定this指向。

注意

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象

this指向例子

例子1:

test() 相当于window.test()调用 即this指向window

注意: 当 开启严格模式 this指向undefined

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

test() // undefined window
1
2
3
4
5
6

例子2:

对象obj在创建之初,this的指向无法确定。

fn通过obj.fn调用之时,根据执行上下文确定了this指向为obj

谁调用的就指向谁

const obj = {
  user: '说不准的',
  fn() {
    // 此时无法确定this 只有当调用之时才能确定
    console.log(this.user)
  }
}
obj.fn() // 说不准的
1
2
3
4
5
6
7
8

例子3:

例子2的时候说 谁调用指向谁,这里需要完善一下。有以下三种情况

1: 如果函数有this,但此函数没有被上级对象调用,那么此this指向window(严格模式下指向undefined)

2: 如果函数有this,这个函数有被上级对象调用,那么此this指向此对象

3: 如果函数有this,这个函数包含多个对象,this也只是指向上层对象,而非最外层对象。

const obj = {
  a: 10,
  b: {
    a:12,
    fn() {
      console.log(this.a)
    }
  }
}
obj.b.fn() // 12
1
2
3
4
5
6
7
8
9
10

例子4:

与例子3 稍微改动下,重新申明个变量接受函数 fn,再执行

结果却是 undefined

始终注意这一点,this是谁调用就指向谁,尽管fn被obj.b 包裹,但是调用之时是 window.fn调用,所以指向window

const obj = {
  a: 10,
  b: {
    a:12,
    fn() {
      console.log(this.a)
    }
  }
}
const fn = obj.b.fn
fn() // undefined
1
2
3
4
5
6
7
8
9
10
11

例子5:

构造函数 this指向

由于是new运算符改变内部this指向

function Fn() {
  console.log(this)
}
const fn = new Fn() // Fn
1
2
3
4

改变this指向

javascript中bind,call,apply改变this指向

注意

1:箭头函数 无法改变this指向 (在哪定义就继承上级执行上下文this)

2:bind 返回一个更改this之后的函数

3:call 第一个参数为this指向,后续为参数化 obj.fn.call({}, 1, 2)

4:apply 第一个参数为this指向,后续为参数类数组 obj.fn.apply({}, [1, 2])

call 实现

改变this指向原理是 谁调用,this指向谁

Function.prototype.myCall = function(ctx, ...args) {
  ctx = ctx || window

  if (typeof ctx !== 'object') {
    ctx = new Object(ctx)
  }

  ctx.fn = this

  const result = ctx.fn(...args)

  delete ctx.fn
  return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

apply 实现

Function.prototype.myApply = function(ctx, ...args) {
  ctx = ctx || window

  if (typeof ctx !== 'object') {
    ctx = new Object(ctx)
  }

  ctx.fn = this

  const result = args.length ? ctx.fn(...args[0]) : ctx.fn() 

  delete ctx.fn

  return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

bind 实现

Function.prototype.myBind = function(ctx, ...args) {
  ctx = ctx || window

  if (typeof ctx !== 'object') {
    ctx = new Object(ctx)
  }

  ctx.fn = this

  return function() {
    const result = ctx.fn(...args, ...arguments)
    delete ctx.fn
    return result
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上次更新: 2021/10/20 下午4:40:42
贡献者: 陈书进