前言
在javascript中this指向可能对于初学者来说确实不太好理解,甚至对于中级开发来说也有点难度,当然可能我也就是其中的一个哈,今天有时间正好来复习下。
正文
在javascript中this有多种使用场景,比如:
- 普通函数中的this
- 箭头函数中的this
- class中的this
- 构造函数中的this
- call、apply、bind
- ...
全局作用域中的this
<script>
console.log(this); //this->window
</script>
this指向window
普通函数中的this
var obj = {
name: "obj的name",
fn1: function() {
console.log(this.name);
},
fn2: function(){
handler()
}
}
function handler(){
console.log(this);
}
obj.fn1() // obj的name
obj.fn2() // window
handler() // Window
首先就是普通函数中的this,直接调用是指通过 handler() 方式调用。简单来说就是谁调用就指向谁,如果是在严格模式下调用那么this就会指向undefined
"use strict"
function handler(){
console.log(this); // undefined
}
handler()
箭头函数中的this
var name = "全局name"
var obj = {
name: "obj的name"
}
var handler = () => {
console.log(this.name);
}
handler() // 全局name
handler.call(obj) // 全局name
箭头函数中的this有点特殊,在定义的时候就已经确定了this的指向,后期无法改变,可以看到打印的结果都是 “全局name”。
构造函数中的this
function Handler(n){
this.name = n
console.log(this)
}
// 作为构造函数使用
var o = new Handler("Lily"); // this为当前对象 Person {name: "Lily"}
// 作为普通函数使用
Handler("Lily"); // Window
- 用new创建对象的时候调用了构造函数。\
- 构造函数和普通函数的区别在于调用方式,而不是定义方式,如果按Handler("Lily")方式调用,他就是个普通函数,由于普通函数中的this是于Window,所以上面函数以Handler("Lily")方式调用后创建了1个全局变量。\
- new关键字改变了函数内this的指向,使其指向刚创建的对象。
window定时器中的this
var name = 'window的name';
var obj = {
name: 'obj的name',
fn: function () {
var timer = null;
clearInterval(timer);
timer = setInterval(function () {
console.log(this.name); // window的name
}, 1000)
}
}
从this.name可以看出this的指向是window。如果没有特殊指向,setInterval和setTimeout的回调函数中this的指向都是window。这是因为JS的定时器方法是定义在window下的。当然如果想要改变他的指向有2种办法,第一种就是在定时器函数外层保存this,在定时器里面使用这个保存this的变量,第二种就是使用call,apply改变他的指向。
call、apply、bind
var name = "window的name";
var obj = {
name: 'obj的name',
}
var handler = () => {
console.log(this.name);
}
handler() // window的name
handler.call(obj, 参数1, 参数2) // obj的name
handler.apply(obj, [参数1, 参数2]) // obj的name
handler.bind(obj, 参数1, 参数2)() // obj的name
可以看到call、apply、bind都可以改变this的指向,不同的是call和apply是直接执行函数的,而bind是返回一个新的函数需要再次执行,call和apply不同的是传参数的方式不同call是一个一个参数传,apply是传数组
class中this的指向
class Handler {
constructor(name) {
this.name = name
}
speak() {
console.log(this)
}
}
const h = new Handler('Callback')
h.speak(); // Person {name: 'Callback'}
实际上,方法内部的 this 永远指向的是调用这个方法的对象,通过 Handler 的实例 p 调用 speak() 方法,那么 this 就指向 p,其实是和es5的构造函数是一样的。
总结: 网上很多文章都说谁调用this就指向谁,不是使用所有的都是,对于普通函数的this指向是对的,但是对于箭头函数,定时器中的this指向就不对了。总之还需平时多发现多积累才能成长,加油!