JavaScript高级 |彻底搞清this指向问题

本文已收录于专栏
⭐️ 《JavaScript》⭐️

this指向问题

this 指向问题 一般情况下 this 的最终指向是那个调用它的对象。

①在全局作用域下或者普通函数中 this 指向全局对象window,包括定时器。

因为在全局作用域下,变量和函数都是window的属性或者方法,所以也就是说他们的调用者就是 window。

console.log(this)
function fun(){
    
    
	console.log(this);
}
本质:
window.function fun(){
    
    
	console.log(this);
}
setTimeout(function(){
    
    
	console.log(this);
},1000);

本质:
window.setTimeout(function(){
    
    
	console.log(this);
},1000);

②方法调用中:谁调用this就指向谁。

调用对象o里面的方法

this指向对象o

var o = {
    
    
  sayHi:fuction(){
    
    
  console.log(this);
  //this 指向的是 o 这个对象
}
}
o.sayHI();

调用 btn 按钮对象

this 指向的是 btn

var bth = document.querySelector('button');

//传统注册事件方法
btn.onclick = function(){
    
    
  console.log(this);
}

//事件监听
btn.addEventListener('click',function(){
    
    
  console.log(this);
})

③构造函数中this指向构造函数中的实例。

在构造函数里调用this

指向的是 Fun的实例对象 fun

function Fun(){
    
    
  console.log(this);
}
var fun = new Fun();

this 绑定规则

默认绑定

独立函数调用都是指向 window

“ 独立的函数调用 ” 我们可以理解成:函数没有被绑定到某个对象进行调用。

  1. 普通函数被独立调用

window是它的绑定对象

function foo(){
    
    
	console.log("foo:",this);
}
foo();
  1. 函数定义在对象里,但是被单独调用

在 ②这种情况中 虽然函数定义在了对象里面,但还是被单独调用,所以此时this 的绑定对象 仍是 window
在 ①这种情况中 函数定义在了对象里面,而且是被对象调用的,所有此时this 的绑定对象是 object
所以 this 的绑定对象,与函数的声明位置没有关系。

var obj = {
    
    
  name:"why",
  bar:function(){
    
    
    console.log("bar:",this)
  }
}
① obj.bar() 
//此时 this 指向的是 objectvar baz = obj.bar
baz();
// 此时 this 指向的是 window
  1. 严格模式下,独立调用的函数中的this 指向都是undefined

一般打包工具会自动将js文件设置成 严格模式,这样可以规避一些低级错误。

"use stric"

function foo(){
    
    
	console.log("foo:",this);
}
foo();

var obj = {
    
    
  name:"why",
  bar:function(){
    
    
    console.log("bar:",this)
  }
}
 var baz = obj.bar
baz();

总结:

  • this 代替 window会比较危险,所以建议直接window来写。
  • 独立函数调用都是指向 window 的!
function foo(){
    
    
	console.log("foo:",window);
}
foo();

隐式绑定

通过某个对象进行调用,即调用位置是某个对象发起的函数调用。

前提:必须在调用的对象内部有一个函数的引用,(比如一个属性)

简单来说就是:将函数赋值给了对象的某个属性,然后通过调用对象的这个属性的方式调用函数就是隐式绑定

function foo(){
    
    
	console.log("foo函数:",this);
}

var obj = {
    
    
	bar:foo
  //将上面声明的那个 foo()函数 赋值给这个 bar 属性
}

obj.bar();
// 调用 obj  对象中的 bar 属性

显式绑定

与隐式绑定不同,显式绑定是通过call()等方法调用自己指定好的this指向的函数。

var obj = {
    
    
  name:"why";
}

function foo(){
    
    
  console.log("foo函数"this}
// 执行函数,并且强制 this 指向 obj 对象
foo.call(obj)

// 可以将 this 指定为 任意对象
foo.call("123")
foo.call(“abc”)


实现显式绑定的两个方法

function foo(name,age,height){
    
    
  console.log("foo函数被调用"this);
  console.log("打印参数",name,age,height);
}

apply()

语法:

foo.applay("apply",["shenqi",18,1.55]);
  • 第一个参数:this 所绑定的对象。例子中 this 绑定的对象为 ‘apply’这个字符串。
  • 第二个参数:额外的实参,需要以数组的形式传入
  • foo.applay(“apply”,[“shenqi”,18,1.55]);

call()

语法:

foo.call("call","shenqi",18,1.55);
  • 第一个参数:this 所绑定的对象。例子中 this 绑定的对象为 ‘call’这个字符串。
  • 参数列表:后续的参数以多参数的形式传递
  • foo.call(“call”,“shenqi”,18,1.55);

总结:第一个函数是相同的,参数均为this所需要指定的对象,后面的参数,apply为数组,call为参数列表.

bind()

我们发现 如果我们想多次调用指定好this指向的函数时都需要调用 apply或者 call。

 foo.applay(); 
 foo.applay(); 
 foo.applay(); 
 foo.applay(); 
 foo.applay(); 
 foo.applay(); 

有没有什么方法可以一劳永逸呢?
bind 便应运而生。
bind本质是 根据调用函数与指定的obj对象生成了一个新的函数,使得指定的obj 对象总绑定在 新的函数上。
独立函数的优先级低的,所以一定是 先执行bind方法绑定之后独立函数才会被执行

var bar = foo.bind()
bar()
bar()
bar()
bar()
bar()

bind方法创建的新的绑定函数(EF)是一个怪异函数对象

new绑定

JavaScript 中的函数可以当做一个类的构造函数来使用,也就是new关键字。
new 之后发生了什么?

  • 创建新的空对象F。
  • 将this指向这个空对象。
  • 指向函数体中的代码。
  • 没有显式返回非空对象时,默认返回这个对象。
function foo(){
    
    
  this.name = "shenqi"
  console.log("foo函数",this// 此时this 就是指向 默认创建的 全新的空对象 
}
new foo()

内置函数的绑定思考

有时候,我们会调用一些JavaScript的内置函数,或者一些第三方库中的内置函数。

  • 这些内置函数会要求我们传入另一个函数
  • 我们自己并不会显式了调用这些函数,都是当事件被触发后JS内部或者第三方库内部帮我们执行;
  • 这些函数中的this又是如果绑定的呢?

需要依靠
image.png

绑定优先级

  1. 默认绑定的优先级最低
  2. 显式绑定的优先级高于隐式绑定

image.png
this 指向:“abc”
在这里插入图片描述

this 指向 :“aaa”

  1. bind 的优先级高于 apply、call

image.png
this指向:“aaa”

  1. new绑定的优先级高于隐式绑定

image.png
this指向:一个空对象 和 false

  1. new绑定的优先级高于bind

在这里插入图片描述
this指向:一个空对象

  1. new和 call、apply是不允许一起使用的,没有可比性。

总结:new>bind>call=apply>默认绑定。
注意:new和 call、apply是不允许一起使用的,没有可比性。

完结散花

ok以上就是对 JS高级篇 |彻底搞清this指向问题 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。

参考文献

coderwhy老师JS高级视频教程

猜你喜欢

转载自blog.csdn.net/m0_66139206/article/details/126807517