# this 指向问题

  • this 总是 (在非严格模式下) 指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数声明时的环境
  • 除了不常用的 with 和 eval 的情况,具体到实际应用中,this 指向大概可以分为以下几种
    • 作为对象的方法调用
    • 作为普通函数调用
    • 构造器调用
    • call 或 apply 调用
    • 箭头函数中,this 指向函数上层作用域的 this
  • 构造器和普通函数的区别在于被调用的方式
  • A.call (B) => 可以理解为在 B 的作用域内调用了 A 方法

# this 指向示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
let name = '老王'

const obj = {
name: '张三',
getName: function() {
console.log(this.name)
}
}

obj.getName() // 输出"张三" 1. 作为对象的方法调用

const getName = obj.getName
getName() // 输出"老王" 2. 作为普通函数调用

function Star(name) {
this.name = name
}

let ldh = new Star('刘德华')
console.log(ldh) // 输出刘德华 3. 作为构造器调用

function foo() {
let _this = this
setTimeout(() => {
console.log(this === _this)
})
}
foo() // 输出"true" 4. 箭头函数指向上层被调用的this

# call 和 apply

# call 和 apply 的区别

  • apply 接受两个参数
    • 第一个参数指定了函数体内 this 对象的指向
    • 第二个参数为一个带下标的参数集合 (可以是数组或伪数组)
  • call 接受的参数不固定
    • 第一个参数指定了函数体内 this 对象的指向
    • 第二个参数以及以后 为函数调用的参数

# call 和 apply 的作用

  • 调用构造函数来实现继承
  • 调用函数并指定上下文的 this
  • 调用函数并且不指定第一个参数

# 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function Animal(name, age) {
this.name = name
this.age = age
}

function Dog(name, age) {
// Animal.call(this, name, age)
Animal.apply(this, [name, age])
this.bark = '汪汪汪'
}

let xiugou = new Dog('多多', 3)
console.log(xiugou) // 输出 Dog { name: '多多', age: 3, bark: '汪汪汪' }


function show() {
console.log(this.value)
}

const obj = {
value: 'hello'
}

show.call(obj) // 输出"hello"


Math.max.apply(null, [1, 3, 5, 6, 7, 8]) //单纯使用apply调用函数(有些地方可以取巧, 例如Math.max函数不接受数组, 使用apply可以将数组转交给max函数)