面向对象语言中 this
表示当前对象的一个引用。但在 JavaScript 中 this
不是固定不变的,它会随着执行环境的改变而改变。
每一个函数内部都有一个关键字this
,并且this
可供直接调用
函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系
-
全局定义的函数直接调用,
this => window
function fn() { console.log(this); } fn(); // 此时 this 指向 window
-
对象内部的方法调用,
this => 调用者
const obj = { fn: function () { console.log(this); } } obj.fn(); // 此时 this 指向 obj
-
定时器的处理函数,
this => window
setTimeout(function () { console.log(this) }, 0) // 此时定时器处理函数里面的 this 指向 window
-
事件处理函数,
this => 事件源
div.onclick = function () { console.log(this) } // 当你点击 div 的时候,this 指向 div
-
自调用函数,
this => window
(function () { console.log(this) })() // 此时 this 指向 window
-
箭头函数,箭头函数内部没有
this
,箭头函数的this
是上下文的 this
// 在箭头函数定义的位置往上查找,这一行是可以打印出 this 的 // 因为这里的 this 是 window // 所以箭头函数内部的 this 就是 window const obj = { fn: function () { console.log(this) }, // 这个位置是箭头函数的上一行,但是不能打印出 this fun: () => { // 箭头函数内部的 this 是书写箭头函数的上一行一个可以打印出 this 的位置 console.log(this) } } obj.fn() obj.fun()
显式函数绑定
在 JavaScript 中函数也是对象,对象则有方法,apply
和 call
就是函数对象的方法。这两个方法异常强大,他们允许切换函数执行的上下文环境(context),即 this
绑定的对象。
-
apply
apply
方法是附加在函数调用后面使用,可以忽略函数本身的this
指向- 语法:
函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...])
const obj = { name: 'Jack' }; function fn(a, b) { console.log(this); console.log(a); console.log(b); } fn(1, 2); // this => window fn.call(obj, [1, 2]); // this => obj
- 使用
apply
:- 会立即执行函数
- 第一个参数是你要改变的函数内部的
this
指向 - 第二个参数是一个 数组,数组里面的每一项依次是向函数传递的参数
-
call
call
方法是附加在函数调用后面使用,可以忽略函数本身的this
指向- 语法:
函数名.call(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...)
const obj = { name: 'Jack' }; function fn(a, b) { console.log(this); console.log(a); console.log(b); } fn(1, 2); // this => window fn.call(obj, 1, 2); // this => obj
- 使用
call
:- 会立即执行函数
- 第一个参数是你要改变的函数内部的
this
指向 - 第二个参数开始,依次是向函数传递参数
-
bind
bind
方法是附加在函数调用后面使用,可以忽略函数本身的this
指向- 和
call / apply
有一些不一样,它不会立即执行函数,而是返回一个已经改变了this
指向的函数 - 语法:
const newFn = 函数名.bind(要改变的 this 指向); newFn(传递参数)
const obj = { name: 'Jack' }; function fn(a, b) { console.log(this); console.log(a); console.log(b); } fn(1, 2); const newFn = fn.bind(obj); // 改变了 this 指向 newFn(1, 2); // 执行结果一致,但是 this => obj const foo = fn.bind(obj, 1); //柯里化,预设置参数 foo(2); // 输出 1,2
总结
this
是作用域内部使用的关键字this
指向不看函数定义,只和调用方式有关- 全局调用
fn() this => window
- 对象调用
obj. fn() this => obj
- 定时器函数
this => window
- 事件处理函数
this => 事件源
- 自执行函数
this => window
- 构造函数
this => 当前实例
- 箭头函数
没有 this ,它的 this 是上下文,即外部作用域的 this
- 全局调用