一.引言
首先我们需要知道:javascript中的this不是指定到一个固定的对象的,它会根据我们函数的调用方式不同,指向不同的对象。
学习this的目的:在面向对象的编程中使用较多,熟悉在不同场景中this的指向,能够帮助我们更好理解代码,代码也会更清晰。
二.this指向的分类
1.this指向window
(1) js文件中的this指向window
(2) 通过函数名+()形式调用函数this指向window
(3) 定时器、延时器回调函数里this指向window
(4) 行内绑定事件(DOM0级)通过函数名+()形式调用this指向window
2.this指向事件调用的节点对象
(1)行内绑定事件时通过函数名+(this)形式,this指向调用的节点对象
(2)DOM1级事件调用,this指向调用的节点对象
(3)DOM2级事件调用,this指向调用的节点对象
3.this指向传入的第一个参数
(1)bind()
(2)call()
(3)apply()
4.this指向对象
(1)通过对象.方法名+()形式调用this指向对象
5.this指向数组
(1)通过数组[下标]+()形式调用,this指向数组
6.this在箭头函数中的指向
(1)箭头函数中this指向它的宿主对象
三.代码讲解
1.this指向window,如果在严格模式下this无法指向全局window
(1) js文件中的this指向window
<script>
// js中直接打印this
console.log(this);//Window {window: Window, self: Window, document: document, name: '', location: Location, …}
</script>
(2) 通过函数名+()形式调用函数this指向window
<script>
function fn(){
console.log(this);//Window {window: Window, self: Window, document: document, name: '', location: Location, …}
}
// 通过函数名()形式调用this指向window
fn()
</script>
(3) 定时器、延时器的回调函数里this指向window
<script>
// 定时器
// setInterval(function(){
// console.log(this); //this指向window,每隔1秒在控制台输出一次
// },1000)
// 延时器
setTimeout(function(){
console.log(this); //延迟1s输出一次this指向window
},1000)
</script>
(4)行内绑定事件(DOM0级)通过函数名+()形式调用this指向window
<body>
<div onclick="clickFn()">这是内容</div>
<script>
function clickFn(){
console.log(this); //点击div时打印出的this指向window
}
</script>
</body>
2.this指向事件调用的节点对象
(1)行内绑定事件时通过函数名+(this)形式,this指向调用的节点对象
<div onclick="clickFn(this)">这是内容</div>
<script>
// str是接收函数传递过来的this,指向的是调用这个事件的节点对象
function clickFn(str){
console.log(str); //str指的是:调用这个<div onclick="clickFn(this)">这是内容</div>
}
</script>
(2)DOM1级事件调用,this指向调用的节点对象,通过节点对象.onclick调用函数称之为DOM1级事件。
<button id='btn'>按钮</button>
<script>
// 获取元素
let btn=document.querySelector('#btn')
// DOM1级事件
btn.onclick=function(){
console.log(this); //结果为:button这个节点对象 <button id="btn">按钮</button>
}
</script>
(3)DOM2级事件调用,this指向调用的节点对象.DOM2级事件是使用节点对象.addEventListener()调用函数。
函数补充:addEventListener('事件名不加on',callback,true/false):true表示冒泡,false表示捕获
<button id='btn'>按钮</button>
<script>
// 获取元素
let btn=document.querySelector('#btn')
btn.addEventListener('click',function(){
console.log(this); //结果指向 button这个节点对象,<button id="btn">按钮</button>
})
</script>
3.this指向传入的第一个参数
(1)bind(this的指向,参数2,参数3):返回一个新函数并改变这个新函数中的this指向bind的第一个参数,后面的参数是调用时给函数传递的参数.
<body>
<ul>
<li>哈哈</li>
<li>呵呵</li>
<li>嘿嘿</li>
<li>嘻嘻</li>
<li>哼哼</li>
</ul>
<script>
// 获取元素节点
let lisObj = document.querySelectorAll('li');
// 使用ES6新增的方法获取元素节点得到的数组可以直接使用数组的方法forEach
lisObj.forEach(function (li) {
// 给每一个Li绑定事件
li.onclick = function () {
// console.log(this); //这个this指向的是调用事件的节点对象
setTimeout(function () {
//原本延时器里面this指向window
// 加个bind改变setTimeout这个函数里面的this指向是bind的第一个参数
console.log(this)
}.bind(this), 1000);
}
});
</script>
</body>
(2)call(this指向,参数2,参数3):调用函数并且改变这个函数中的this指向。
<script>
function Fn1(name,age){
this.name=name
this.age=age
// console.log('Fn1中this的指向',this); //原本this指向Fn1实例化的对象
console.log('Fn1中this的指向',this) //现在Fn1中this的指向为Fn2 {score: 100, name: 'zs', age: 19}
}
function Fn2(name,age,score){
this.score=score
// 使用call这个函数,改变Fn1中this的指向call里面的第一个参数this
// 第一个参数this是指的Fn2这个实例化的对象
// 并且调用Fn1这个函数
Fn1.call(this,name,age)
}
// 实例化Fn2的对象
let f2=new Fn2('zs',19,100)
</script>
(3)apply(this的指向,数组[]):调用函数并改变这个函数中的this指向。
<script>
function Fn1(name,age){
this.name=name
this.age=age
// console.log('Fn1中的this指向:',this); //原来Fn1中的this指向: Fn1 {name: 'ls', age: 20}
console.log('Fn1中的this指向:',this); //现在Fn1中的this指向: Fn2 {score: 80, name: 'zs', age: 29}
}
// let f1=new Fn1('ls',20)
function Fn2(name,age,score){
this.score=score
// 这里的this指向的是Fn2实例化的对象
Fn1.apply(this,[name,age])
}
let f2=new Fn2('zs',29,80)
</script>
4.this指向对象
(1)通过对象.方法名+()形式调用this指向对象
<script>
let obj={
name:'zs',
age:18,
score:90,
say(){
console.log(this); //this指向的是对象:{name: 'zs', age: 18, score: 90, say: ƒ}
}
}
obj.say()
</script>
5.this指向数组
(1)通过数组[下标]+()形式调用,this指向数组
<script>
function fn(){
console.log(this); //this指向数组:['a', 'b', 'c', ƒ]
}
// 数组元素是函数名
let arr=['a','b','c',fn]
// 通过数组名下标+()调用函数,this指向数组
arr[arr.length-1]()
</script>
6.this在箭头函数中的指向
(1)箭头函数中this指向它的宿主对象
<div>这是内容</div>
<script>
// 获取元素(
let div=document.querySelector('div')
// 给div元素绑定事件
div.onclick=function(){
// console.log(this); //this指向调用事件的节点对象:<div>这是内容</div>
setInterval(() => {
console.log(this); //原本里面的this指向的是window,使用箭头函数,就指向它的宿主对象(也就是它的上一级):<div>这是内容</div>
}, 2000);
}
</script>
四.总结
总之,this在不同的调用方式下指向不同的对象,小伙伴们可以熟记一些常见的this指向。