首先我们要清楚什么是this指向?
只要是写代码的,都知道this随处可见,我们必须要清楚this是js语言的一个关键字,代表函数运行时自动生成的一个内部对象,只能在函数内部使用,随着使用场合的不同,this的值也会发生变化。this指向都遵循一个基本原则:一般谁调用this,this就指向谁。这么讲可能有点太广泛了,接下来先介绍this指向的几个场景。
this在不同环境下、不同作用下,表现的也不同。
以下是this指向的几个场景。
一、this指向场景
1.全局作用下,this指向window
直接控制台打印this,打印出来的是window对象,默认情况下,this指向的就是window。
console.log(this) //window
2.函数独立调用时,this指向window
非严格模式下,函数内部的this指向的就是window。
function fun(){
console.log(this)
}
fun() //Window
如果是在严格模式下,this指向的就是undefined。这里要介绍一下'use strict'。
'use strict':表示使用严格模式。
优点:消除了JavaScript语法的一些不严谨的地方,提高了编译器效率,增加了运行速度,保证代码运行的安全。
缺点:严格模式改变了语义,依赖这些改变可能会导致没有实现严格模式的浏览器出现错误。
'use strict'
function fun(){
console.log(this)
}
fun() //undefined
3.被嵌套的函数独立调用时,this默认指向window
函数里面在嵌套一个函数,this指向还是window。
function fun1(){
function fun2(){
console.log(this) //Window
}
fun2()
}
fun1()
4.IIFE(立即执行函数)中内部的this指向也是window
立即执行函数也叫自调用函数,简单来说就是自己调用自己。就是在函数创建后让其立即执行。
(function(){
console.log(this) //Window
})()
5.定时器中的this指向window
定时器又分为循环定时器(setInterval)和延时定时器( setTimeout),他们内部的this指向也是window。单位是毫秒,1000毫秒代表1秒。
setInterval(function(){
console.log(this); //window
},1000)
6.构造函数中的this,指向new关键字生成的实例化对象
构造函数中的this,用于给实例化对象添加方法和属性,指向的是实例化对象。
new关键字四步:1.new在构造函数体内创建一个空的对象;2.将this指向刚创建好的空对象;3.执行构造函数体内的代码,给空对象添加属性和方法;4.返回this,即创建好的对象。
function Fun(){
console.log(this) //Fun()
}
var fn = new Fun()
7.当有事件绑定时,this指向绑定的事件对象
点击btn按钮时,this就会指向button。click:点击事件。
<button>123</button>
<script>
var btn = document.getElementsByTagName('button')[0]
btn.onclick = function(){
console.log(this) //<button>123</button>
}
</script>
8.对象里的方法被调用时,this指向该对象
function fun(){
console.log(this) //obj
}
var obj = {
fon:fun
}
obj.fon()
9,箭头函数中this指向
箭头函数中不会创建自己的this,如果在箭头函数中有,它只会向上一层函数中查找this,直到查到window。
下面的代码中,传给getAge函数内的this并不是调用者的,而是外部的this。
this.age = 123;
var obj = {
age : 1,
getAge: () =>{
console.log(this.age) //123
}
}
obj.getAge()
二、改变this指向
1.call()方法
call(将this指向谁,(可选)参数列表)
格式:函数名.call()
this指向从window变成了call。
var obj = {
a:100,
b:20,
}
function fun(a,b){
console.log(this) //obj
console.log(a+b); //3
}
fun.call(obj,1,2)
2.apply()方法
call(将this指向谁,(可选)数组列表)
格式:函数名.apply()
var obj = {
a:100,
b:20,
}
function fun(a,b){
console.log(this) //window -> obj
console.log(a+b); //3
}
fun.apply(obj,[1,2])
3.bind()方法
bind(将this指向谁,(可选)参数列表)
格式:函数名.bind()
不改变原函数的this,bind会返回一个跟原函数一模一样的新函数,新函数中this指向被修改了
var obj = {
a:100,
b:20,
}
function fun(a,b){
console.log(this) //obj
console.log(a+b); //10
}
var newFun = fun.bind(obj)
newFun(5,5)
需要注意的是call()和apply()的作用基本一致,区别在于参数的传递方式不同,一个是传参数,一个是传数组。但他们最大的作用就是改变this指向。