【JavaScript】聊聊js中关于this的指向
前言
最近在看回JavaScript的面试题,this 指向问题是入坑前端必须了解的知识点,现在迎来了ES6+的时代,因为箭头函数的出现,所以感觉有必要对 this 问题梳理一下,所以刚好总结一下JavaScript中this指向的问题。
什么是JavaScript
在了解this指向的问题前,首先得了解一下什么是JavaScript。
JavaScript(简称“JS”)是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。JavaScript基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式、声明式、函数式编程范式、支持函数式编程、闭包、基于原型的继承等高级功能。
什么是this
面向对象语言中 this 表示当前对象的一个引用。
但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
在方法中,this 表示该方法所属的对象。
如果单独使用,this 表示全局对象。
在函数中,this 表示全局对象。
在函数中,在严格模式下,this 是未定义的(undefined)。
在事件中,this 表示接收事件的元素。
类似 call() 和 apply() 方法可以改变 this 的指向 ,引用到任何对象。
所以this的指向完全取决于函数的调用方式。
this的指向
接下来我将在(非严格模式下)通过下面例图与例子来了解this的指向。
1.不使用new关键字,使用dot调用。
var obj = {
name: 'bug',
obj2: {
name: 'bug2',
fn: function () {
console.log(this.name); //bug2
}
}
}
//此处通过obj.obj2.fn(),调用了obj中的obj2中的fn函数,此时fn函数中this的指向为dot (.) 前面的对象,即为obj2,obj2中的name即是bug2。
obj.obj2.fn();
2.使用new关键字调用。
function fn() {
this.x = 1;
}
//此处通过new关键字生成了一个实例对象,此时的this指向了该实例对象fn
var obj = new fn();
//此时的obj的结构为{x:1},所以obj.x=1
obj.x // 1
讲到new关键字就刚好衍生出看另外一个关键点,如果我用new去创建一个实例对象,这个时候实例对象有返回值呢?
通常情况下是不应该有显式的返回值的。
但是如果当return返回的是一个对象,那么将返回该对象。
但是如果当return返回非对象类型(比如数字、字符串等),那么就不会影响到new关键字对对象的创建。
以下就用几个例子来验证一下:
①return 空对象
function fn()
{
this.name= 'bug';
//此处return回了一个对象
return {};
}
var obj = new fn();
//此时因为return回的是一个对象,所以此时的obj的结构是返回的空对象{},所以obj.name才会是undefined
console.log(obj.name); //undefined
②return一个非空对象
function fn()
{
this.name= 'bug';
//此处return回了一个对象
return {name:'bug2'};
}
var obj = new fn();
//此时因为return回的是一个非空对象,所以此时的obj的结构是返回的非空对象{name:'bug2'},所以obj.name是bug2
console.log(obj.name); //bug2
③返回数字
function fn()
{
this.name= 'bug';
//此处return回了一个数字
return 11;
}
var obj = new fn();
//此时因为return回的是一个数字,所以此时返回的实例对象不受影响,结构是{name:'bug'},所以obj.name是bug
console.log(obj.name); //bug
④返回字符串
function fn()
{
this.name= 'bug';
//此处return回了一个字符串
return 'xxxxx';
}
var obj = new fn();
//此时因为return回的是一个字符串,所以此时返回的实例对象不受影响,结构是{name:'bug'},所以obj.name是bug
console.log(obj.name); //bug
既然现在进入了Es6+的时代了,就不得不讲一讲箭头函数的this指向了
1.什么是箭头函数
箭头函数是ECMAScript 6中新增的一种函数定义方式,也被称为Lambda函数。 它使用箭头(=>)符号来替代传统的function关键字,从而更简洁地定义函数,使代码更加简洁易读。
箭头函数有以下特点:
①语法简洁:箭头函数表达式的语法比普通函数更简洁,使用箭头(=>)符号来定义函数,可以省略一些不必要的语法元素,如function关键字、大括号和参数列表周围的括号(如果只有一个参数)。
②this绑定:箭头函数不绑定自己的this,它会捕获定义时所在上下文的this值,这使得在回调函数或嵌套函数中使用箭头函数时,this的指向更加明确和可预测。
③没有arguments对象:箭头函数没有自己的arguments对象,这意味着它们无法访问到传统函数的特殊属性arguments。
④不能用作构造器:箭头函数不能作为构造器使用,即它们不能用作类的实例化。
2.箭头函数的this指向
因为箭头函数不绑定自己的this,它会捕获定义时所在上下文的this值。所以简单的说就是箭头函数没有属于自己的this。
一下用个例子来简单了解。
①正常function函数
const obj={
mythis: function(){
console.log(this) //指向了上一级对象obj
}
}
obj.mythis() //返回了obj对象
②箭头函数
const obj={
mythis: ()=>{
console.log(this) //因为箭头函数没有自己的this,所以指向的是window
}
}
obj.mythis() //返回了window
哦这里还有一个坑,就是前面说的,this指向完全取决于函数的调用方式。
你再看看这道题最终返回的是什么?
const obj={
mythis: function(){
console.log(this)
}
}
var a =obj.mythis
a()
点击查看答案与解析
//是不是有小伙伴认为这里使用的是function,所以返回的还是mythis的上一级对象obj ???
//不不不,这时候返回的是window!因为this指向完全取决于函数的调用方式
//上述例子①为何返回的是obj是因为它是直接obj.mythis()去调用,this指向是mythis的上一级对象
//但是本例子是通过减mythis直接赋值给a,此时,a 成为一个普通的函数引用,它只是 obj.mythis 的一个复制,并没有 obj 对象的上下文信息
//所以,当 a 作为一个普通函数调用时(不作为对象的方法调用),在非严格模式下,JavaScript 中的 this 默认指向全局对象 window
const obj={
mythis: function(){
console.log(this)
}
}
var a =obj.mythis
a() //window
当然,this的指向除了调用的方式不同而不同的同时,也可以通过其它方式强制改变this的指向!那就是使用call、apply、bind。
什么是call、apply、bind,区别是什么?
1.什么是call?
call方法可以接受两个参数,第一个参数就是this的指向,指向xxx,第二个参数为一个参数列表。当第一个参数为null或者undefined时,this默认指向window。
function fn(...args) {
console.log(this, args);
}
let obj = {
name: "bug"
}
//将fn的this指向obj,并传入参数列表 1,2
fn.call(obj, 1, 2); //{name:'bug'} , [1,2]
//次数fn中的this指向为window
fn(1, 2) //window , [1,2]
//当第一个参数为null时,this指向为window
fn.call(null,[1,2]);//window , [1,2]
//当第一个参数为undefined时,this指向为window
fn.call(undefined,[1,2]);//window , [1,2]
2.什么是apply?
apply方法可以接受两个参数,第一个参数就是this的指向,指向xxx,第二个参数为一个参数数组。当第一个参数为null或者undefined时,this默认指向window。
function fn(...args) {
console.log(this, args);
}
let obj = {
name: "bug"
}
//将fn的this指向obj,并传入参数数组 [[1,2]]
fn.apply(obj, [1,2]); //{name:'bug'} , [[1,2]]
//次数fn中的this指向为window
fn([1,2]) //window , [[1,2]]
//当第一个参数为null时,this指向为window
fn.apply(null,[1,2]);//window , [[1,2]]
//当第一个参数为undefined时,this指向为window
fn.apply(undefined,[1,2]);//window , [[1,2]]
3.什么是bind?
bind方法跟call、apply十分相似,第一个参数也是this的指向,第二个参数传的也是一个参数列表,但是!这个参数列表可以分多次传入!并且改变完this的指向并不会立刻执行,而是返回一个已经永久改变this指向的函数
function fn(...args) {
console.log(this, args);
}
let obj = {
name: "bug"
}
const bindFn = fn.bind(obj); //this变为obj,且不会立马执行
bindFn(1, 2) //得通过调用才会执行,并传入参数列表1,2,最终this指向obj {name:'bug'}
fn(1, 2) //this执行window
4.call、apply、bind的区别是什么?
①三者都可以改变函数的 this 对象指向
②三者第一个参数都是 this 要指向的对象,如果如果没有这个参数或参数为 undefined 或 null,则默认指向全局 window
③三者都可以传参,但是 apply 是数组,而 call 是参数列表,且 apply 和 call 是一次性传入参数,而 bind 可以分为多次传入bind 是返回绑定this之后的函数,apply、call 则是立即执行
总结
简单来说,this的指向不是固定不变的,它会随着执行环境的改变而改变,具体怎么改变完全取决于函数的调用方式。
箭头函数没有属于自己的this,作为方法的箭头函数this的指向是当前的上下文。
我是刚毕业一年多的小菜鸟,上述为个人学习整理内容,水平有限,如有错误之处,望各位园友不吝赐教!如果觉得不错,请点击推荐和关注!谢谢~๑•́₃•̀๑ [鲜花][鲜花][鲜花]
【JavaScript】聊聊js中关于this的指向的更多相关文章
- 聊聊js中的typeof
内容: 1.typeof 2.值类型和引用类型 3.强制类型转换 typeof 官方文档:typeof 1.作用: 操作符返回一个字符串,指示未经计算的操作数的类型. 2.语法: typeof ope ...
- 从Ecma规范深入理解js中的this的指向
this是面向对象编程中的一个概念,它一般指向当前方法调用所在的对象,这一点在java.c++这类比较严格的面向对象编程语言里是非常明确的.但是在javascript中,this的定义要灵活许多,如果 ...
- 理解JS中的this的指向
原文地址:https://www.cnblogs.com/pssp/p/5216085.html#1 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到 ...
- js中函数this的指向
this 在面试中,js指向也常常被问到,在开发过程中也是一个需要注意的问题,严格模式下的this指向undefined,这里就不讨论. 普通函数 记住一句话哪个对象调用函数,该函数的this就指向该 ...
- Javascript基础 - js中曾经忽略的知识点
深入那些曾经忽略的Javascript知识 1. parseInt(string, [radix]),parseFloat(string) 一般我们省略第二个参数,parseInt(‘100’) == ...
- html css <input> javaScript .数据类型 JS中的函数编写方式 BOM总结 DOM总结
Day27 html css div 块标签. 特点: 独占一行,有高度和宽度 span 行元素. 特点:在同一行显示,当前行满了自动去下一行显示. 不识别高度和宽度 1.1.1.1 2.输入域标签 ...
- 【JavaScript】js 中一些需要注意的问题
关于js中逻辑运算符 sort()方法 1. 关于js中逻辑运算符:|| 和 && 在js逻辑运算中,0."".null.false.undefined.NaN都会 ...
- 咱们来聊聊JS中的异步,以及如何异步,菜鸟版
为什么需要异步?why?来看一段代码. 问题1: for(var i=0;i<100000;i++){ } alert('hello world!!!'); 这段代码的意思是执行100...次后 ...
- 【JavaScript】js中的call方法
moziila官方文档链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Funct ...
- js中的this的指向问题
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象 this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调 ...
随机推荐
- WEB服务与NGINX(20)- nginx 实现HTTP反向代理功能
目录 1. nginx实现反向代理功能 1.1 nginx代理功能概述 1.2 NGINX实现HTTP反向代理 1.2.1 HTTP反向代理基本功能 1.2.1.1 反向代理配置参数 1.2.1.2 ...
- kettle使用2-增量插入
1.新建转换 2.在DB连接中,新建2个数据库连接 3.在输入中,新建:表输入 4.在输入中,新建:表输入 5.在输出中,新建:表输出
- MQ消息积压,把我整吐血了
前言 我之前在一家餐饮公司待过两年,每天中午和晚上用餐高峰期,系统的并发量不容小觑. 为了保险起见,公司规定各部门都要在吃饭的时间轮流值班,防止出现线上问题时能够及时处理. 我当时在后厨显示系统团队, ...
- 逆向WeChat(三)
本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/18198572 上篇回顾,对象是WEUIEngine.WeUIEngine使用了chrome::base框架,但只用 ...
- 部署springboot+vue项目文档(若依ruoyi项目部署步骤)
摘自:https://blog.csdn.net/Dreamboy_w/article/details/104389797 部署springboot+vue项目文档(若依ruoyi项目部署步骤)一:部 ...
- BigDecimal类的基本使用
概述 java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数.在实际应用中,需要对更大或者更小的 ...
- 8.18考试总结(NOIP模拟43)[第一题·第二题·第三题·第四题]
愿你和重要的人,在来日重逢. 前言 题目名字起的很随意... 这天 Luogu 的运势好像是大凶(忌:打模拟赛,注意报零). 但是考得还不错,拿到了这么多场模拟赛以来第二三个场上AC. 所以说,我爱大 ...
- 深度学习论文翻译解析(二十二):Uniformed Students Student-Teacher Anomaly Detection With Discriminative Latent Embbeddings
论文标题:Uniformed Students Student-Teacher Anomaly Detection With Discriminative Latent Embbeddings 论文作 ...
- else if
// if(){}else if(){}...else{} // 多种条件,多种情况下的判断语句 // 必须要注意 // 1,else if 之后有 ...
- linux,curl命令发送各类请求详解
当你经常面对api时,curl将是你重要学习的工具,因为curl可以让你不需要浏览器也能作为Http客户端发送请求.而且它是跨平台的,Linux.Windows.Mac都会执行的很好. 一.curl ...