0 核心思想
this永远指向函数的直接调用者- 如果有new关键字,则
this指向new出来的对象 - 在事件中,
this指向触发这个事件的对象(IE例外)
一般来说,函数的调用有以下几种方式
func(p1, p2)
obj.child.method(p1, p2)
func.call(context, p1, p2)
可以将前两种都转化为最后一种进行表达,也就是说this实际执行的就是函数调用时传入的上下文,根据调用时传入的上下文对象决定this
常见问题1
var obj = {
foo: function(){
console.log(this)
}
}
var bar = obj.foo
obj.foo() // 转换为 obj.foo.call(obj),this 就是 obj
bar()
// 转换为 bar.call()
// 由于没有传 context
// 所以 this 就是 undefined
// 最后浏览器给你一个默认的 this —— window 对象
[ ] 语法
function fn (){ console.log(this) }
var arr = [fn, fn2]
arr[0]() // 这里面的 this 又是什么呢?
可以将数组下标按下面代码的方式转换
arr[0]()
假想为 arr.0()
然后转换为 arr.0.call(arr)
那么里面的 this 就是 arr 了 :)
箭头函数
不影响this,直接将上一级的结果传递进来。 举例
function a() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(a()()())
this在本质上是最外层的this指向,即window
call, apply, bind
首先分析作用相似的call, apply
call和apply都是为了解决改变this的指向。作用都是相同的,只是传参的方式不同。- 除了第一个参数外,
call可以接收一个参数列表,apply只接受一个参数数组
let a = {
value: 1
}
function getValue(name, age) {
console.log(name)
console.log(age)
console.log(this.value)
}
getValue.call(a, 'yck', '24')
getValue.apply(a, ['yck', '24'])
bind参数与call类似,但返回的是函数
let a = {
value: 1
}
function getValue(name, age) {
console.log(name)
console.log(age)
console.log(this.value)
}
getValue.bind(a, 'yck', '24')()
连续bind的结果由第一次bind决定
let a = {}
let fn = function () { console.log(this) }
fn.bind().bind(a)() // => ?
可以将bind转化为返回函数的apply形式
// fn.bind().bind(a) 等于
let fn2 = function fn1() {
return function() {
return fn.apply()
}.apply(a)
}
fn2()
总结
this执行主体,谁把它执行的和在哪创建的在哪执行的都没有必然的关系
- 函数执行,看方法前面是否有点,没有点
this是window(严格模式下是undefined),有点,点前面是谁·this·就是谁 - 给当前元素的某个事件行为绑定方法,当事件行为触发,方法中的this是当前元素本身(排除IE的
attachEvent) - 构造函数体中
this是当前类的实例 - 箭头函数中没有执行主体,所用到的this都是所处上下文中的
this - 可以基于
Function.prototype上的call/apply/bind改变this指向