最初学习js时,对this指向只有些皮毛的理解,随着学习的逐渐深入后,尝试查找文档去细致理解,但都不够完整,近期看了一个很厉害的大神的视频课后,跟着他的脚步总结出比较直观的方式解析。文章的文字性的叙述较少偏重于通过案例解析,希望看到这篇文章的你也能有所获益
目录
1.this在全局作用域指向什么
在大多数情况下,this出现在函数中
全局作用域下:浏览器:window(golobalObject) ; Node环境:{}空对象
2.this绑定规则
2.1默认绑定
函数绑定规则
(独立函数调用)独立调用时,this指向全局(window)
// 案例一:
function foo(){
console.log(this)//window
}
foo()
// 案例二:其函数在被调用时都是独立的函数
function one(){
console.log(this);//3.window
}
function two(){
console.log(this);//2.window
one()
}
function three(){
console.log(this);//1.window
two()
}
three()//window
// 案例三:
var obj = {
name :"why",
foo:function(){
console.log(this);
}
}
// obj.foo()
var bar = obj.foo
bar() //window
小tips:只要最后函数是被单独调用的,其this指向为window
2.2.隐式绑定
隐式绑定: object.fn()
object对象会被js引擎绑定到fn函数中的this里面
// 案例一:
function foo(){
console.log(this);
}
var obj = {
name : "why",
foo:foo
}
obj.foo() //obj
// 案例二
var obj1 ={
name:"obj1",
foo:function(){
console.log(this);
}
}
var obj2={
name:"obj2",
bar:obj1.foo
}
obj2.bar()//obj1
2.3.显式绑定
默认绑定和显示绑定冲突时:显示绑定优先级高
显式绑定call/apply/bind,在执行函数时,可以明确的绑定this,这个绑定规则为显示绑定
function foo(){
console.log("函数被调用了",this);
}
// 直接调用与通过call/apply调用的不同在于this的绑定不同
// foo直接调用指向全局对象(winow)
// call/apply调用指定this的绑定对象
foo() //this指向window
foo.apply() //this指向obj
foo.call() //this指向obj
foo.apply("aaa") //this指向aaa
call/apply的区别
function sum(num1,num2,num3){
console.log(num1+num2+num3,this);
}
sum.call("call",10,20,30) //所传参数直接书写
sum.apply("apply",[10,20,30]) //所传参数需以数组的格式书写
// 默认绑定和显示绑定冲突时:显示绑定优先级高
bind
将一个函数总是显示的绑定到一个对象上
var newBar = bar.bind("aaa")
newBar()//this指向"aaa"
2.4.new绑定
1.创建一个全新的对象
2.会被执行的prototypel连接
2.这个新对象会绑定到函数的this上
// 通过一个new关键字调用一个函数时,这个this就是在调用函数时创建的对象
// this=创建出来的对象
// 其绑定过程就是new绑定
function Person(name,age){
console.log(this);//Person
this.name = name
this.age = age
}
var p1 = new Person("why",18)
console.log(p1.name, p1.age,this); //"why",18,window
var p2 = new Person("look",30)
console.log(p2.name, p2.age,this);//"look",30,window
3.特殊函数的this分析
3.1.定时器函数
其内部函数指向看如何调用,一般都是独立调用
setTimeout(function(){
console.log(this); //window
},2000)
3.2.监听点击
相当于隐式绑定:boxDiv.onlick()
const boxDiv = document.querySelector('.box');
//案例一:
boxDiv.onclick = function() {
console.log(this); // <div class="box"></div>
// 相当于隐式绑定
// boxDiv.onlick()
}
//案例二:
boxDiv.addEventListener('click',function(){
console.log(this); //<div class="box"></div>
})
3.3.数组
forEach/map/fillter/find:可以将this指向当作第二个参数传递
var eat = ["cake","milk","yoghurt"]
eat.forEach(function(item){
console.log(item,this); //this指向window
})
// 进行指向固定
var eat = ["cake","milk","yoghurt"]
// forEach函数中可将this指向当作第二个参数传递
eat.forEach(function(item){
console.log(item,this); //this指向"abc"
},"abc")
4.规则优先级
4.1.默认绑定优先级最低
4.2.显式绑定高于隐式绑定
var obj ={
name:"obj",
foo:function(){
console.log(this);//"abc"
},
}
obj.foo.call('abc')
obj.foo.apply('abc')
//bind优先级高于隐式绑定
function foo(){
console.log(this);//{"aaa"}
}
var obj = {
name:"obj",
foo:foo.bind("aaa")
}
obj.foo()
4.3.new绑定优先级高于隐式绑定
var obj={
name:"obj",
foo:function(){
console.log(this);
}
}
// 1.如果隐式绑定优先级高于new绑定时输出结果:obj
// 2.如果new绑定优先级高于隐式绑定时输出结果:foo()
var p = new obj.foo() //foo