当前位置:网站首页>js 中this指向
js 中this指向
2022-08-02 03:23:00 【星雨668】
一、前言
在js中,this关键字重要,很多同学工作几年了,依然对this问题很模糊,通过这篇文章希望能够帮助到大家,深刻理解this。
二、this的本质是什么?
在js中,所有的函数(除了箭头函数),内部都会有一个属性this,当调用函数的方式不同时,this的指向也有所不同。
三、绑定this的方式有哪些?
绑定this的方式一般包含一下几种:
- 默认绑定(一般this指向window)
- 隐式绑定(谁调用,指向谁,存在隐式丢失问题)
- 显式绑定(call、apply、bind 能改变this指向)
- new 实例化
- es6中箭头函数(内部没有this属性,输出的是父级上下文的this)
绑定this的优先级:箭头函数 > new > 显式绑定 > 隐式绑定 > 默认绑定
四、this的默认绑定
代码:
function foo(){
console.log(this);
}
foo() // Window
解读:当函数被直接调用时,this默认指向window。
五、this的隐式绑定
代码:
function foo(){
console.log(this);
}
let obj = {
name:1,
foo:foo
}
// 隐式绑定,对象调用,谁调用,指向谁
obj.foo(); // {name: 1, foo: ƒ}
// 赋值给一个变量,再调用,隐式绑定丢失
let temp = obj.foo;
temp(); // Window
解读:1、函数foo,被obj以属性的方式调用时,属于隐式绑定规则,谁调用,this就会指向谁,所以this指向obj;
2、存在隐式绑定丢失情况,如以上代码,将obj.foo赋值给一个新的变量,此时调用等同于直接调用,所以this指向window。
六、this的显式绑定
代码:
function foo(params){
this.age = params
console.log(this);
}
let obj = {
foo:foo
}
let obj1 = {
name:1,
}
let obj2 = {
name:2,
}
let obj3 = {
name:3,
}
obj.foo.call(obj1,18) // {name: 1, age: 18}
obj.foo.apply(obj2,[19]) // name: 2, age: 19}
obj.foo.bind(obj3,20)() // {name: 3, age: 20}
obj.foo.call(null,21) // Window
解读:通过call、apply、bind都可以显式的改变this指向,并且优先级高于隐式绑定。
七、new关键字实例化
代码:
function foo(params){
this.age = params;
console.log(this); // foo {age: 18}
}
let obj = {
foo: foo
}
let obj1 = {
name:1
}
let temp = obj.foo.bind(obj1)
let foo1 = new temp(18)
console.log(foo1); // foo {age: 18}
console.log(obj1); // {name: 1}
解读:先使用bind改变this指向obj1,在使用new实例化一个对象,通过输出可以看出,当前this指向是foo1,并不是指向obj1,故,this绑定,new关键字优先于显式绑定
八、特殊案例“箭头函数”
代码:
let obj = {
foo:()=>{
console.log(this)
}
}
let obj1 = {
name:1,
}
obj.foo.call(obj1) // Window
// 箭头函数和new关键字,在一起如何呢?
let temp = obj.foo.bind(obj1)
let foo1 = new temp() // 报错:temp is not a constructor
解读:1、箭头函数内部没有this,输出的this是父级上下文的this,所以即使用call也无法改变,最终还是指向Window;
2、当new关键字和箭头函数一起使用时会报错:is not a constructor,所以箭头函数不能被当做构造函数
练习
var name = 'window'
let obj1 = {
name:1,
fn1: function(){
console.log(this.name)
},
fn2: ()=>console.log(this,name),
fn3: function () {
return function(){
console.log(this.name)
}
},
fn4:function () {
return ()=>console.log(this.name)
}
}
let obj2 = {
name:2
}
obj1.fn1(); // 1
obj1.fn1.call(obj2); //2
obj1.fn2(); // 'window'
obj1.fn2.call(obj2); // 'window'
obj1.fn3()(); // 'window'
obj1.fn3().call(obj2); // 2
obj1.fn3.call(obj2)(); // 'window'
obj1.fn4()(); // 1
obj1.fn4().call(obj2); // 1
obj1.fn4.call(obj2)(); //2
大家做对了吗? 欢迎大家留言评论
边栏推荐
- meime模块
- meime module
- DSPE-PEG-DBCO Phospholipid-Polyethylene Glycol-Dibenzocyclooctyne A Linear Heterobifunctional Pegylation Reagent
- ssm various configuration templates
- display,visibility,opacity
- URL URL
- [Learning Records of Boxue Valley] Super summary, share with heart | Software Testing Interface Testing Basics
- Guangzhou Huawei Interview Summary
- 微信小程序云开发-证件照的实现
- 1.10今日学习
猜你喜欢
随机推荐
配置mmdet来训练Swin-Transformer之一配置环境
我的小笔记 =》原生微信小程序
Knowledge Engineering Assignment 2: Introduction to Knowledge Engineering Related Fields
语义分割标签即像素值的巨坑,transforms.ToTensor()的错误使用
js作用域与闭包
js scope and closure
Phospholipid-polyethylene glycol-azide, DSPE-PEG-Azide, DSPE-PEG-N3, MW: 5000
猴子选大王
C语言 十六进制整数字符串转十进制整数
STM32 触发HardFault_Handler如何查找原因
Source Insight 使用教程(2)——常用功能
meime模块
第一篇博客
微信小程序实现文本安全监测
啃瓜记录第一天
[Learning Records of Boxue Valley] Super summary, share with heart | Software Testing Interface Testing Basics
docker中配置mysql 5.7
meime module
利用 nucleo stm32 f767zi 进行USART+DMA+PWM输入模式 CUBE配置
npm and package.json