当前位置: 首页 > news >正文

JS中this的值详细讲解以及面试指向练习

this 的值取决于它出现的上下文:函数、类或全局。

在函数内部,this 的值取决于函数如何被调用,this 是语言在函数体被执行时为你创建的绑定

对于典型的函数,this 的值是函数被访问的对象。换句话说,如果函数调用的形式是 obj.f(),那么 this 就指向 obj,例如

function getThis() {return this;
}const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };obj1.getThis = getThis;
obj2.getThis = getThis;console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] }
console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] }

注意,虽然函数是相同的,但是根据其调用的方式,this 的值是不同的。这与函数参数的工作方式类似。

this到底指向谁

调用函数会创建新的属于函数自身的执行上下文,执行上下文的调用创建阶段会决定this的指向,结论:this的指向,是在调用函数时根据执行上下文所动态确定的,或者说this关键字指向函数(方法)运行时的所有者

1.规则:

  • 在函数体中,简单调用该函数时(非显式/隐式绑定下),严格模式下this绑定到undefined,否则绑定到全局对象window/global
  • 一般构造函数new调用,绑定到新创建的对象上
  • 一般由call/bind/apply方法显式调用,绑定到指定参数的对象上
  • 一般由上下文对象调用,绑定在该对象上
  • 箭头函数中,根据外层上下文绑定的this决定this的指向

2.实例分析练习

(1)全局环境下的this

function f1(){console.log(this);
}function f2() {'use strict'console.log(this);
}f1()  //Window对象
f2()  //undefined
const foo = {bar: 10,fn: function () {console.log(this);  //Windowconsole.log(this.bar);  //undefined}
}var fn1=foo.fn
fn1()

上题中this指向的是window,虽然fn函数在foo对象中作为方法被引用,但是在赋值给fn1后,fn1的执行仍然是在window的全局环境中

const foo = {bar: 10,fn: function () {console.log(this);  //{bar:10,fn:f}console.log(this.bar);  //10}
}foo.fn()

上题中this指向的是最后调用他的对象,在foo.fn()语句中this指向foo对象

注意:在执行函数时,如果函数中的this是被上一级的对象所调用,那么this指向的就是上一级的对象;否则指向全局环境

 (2)上下文对象调用中的this

const student={name:'hist',fn:function(){return this}
}console.log(student.fn()===student); //true
const person = {name: 'hist',brother: {name: 'comp',fn: function () {return this.name}}
}console.log(person.brother.fn());  //comp

上题在这种嵌套关系中,this指向最后调用它的对象

const o1 = {text: 'o1',fn: function () {return this.text}
}const o2 = {text: 'o2',fn: function () {return o1.fn()}
}const o3 = {text: 'o3',fn: function () {var fn= o1.fnreturn fn()}
}console.log(o1.fn()); //o1
console.log(o2.fn()); //o1
console.log(o3.fn()); //undefined

第二个相当于最后调用时还是用o1调用的fn()

第三个将o1.fn()赋值给fn后,直接调用fn(),没有用对象点调用,所以这里this指向window

如果想让第二个输出o2怎么做?

const o2 = {text: 'o2',fn: o1.fn()
}

此时我们将赋值操作提前,相当于先把o1.fn()变为this.text,此时我们用o2调用fn()指向的就是o2对象

  (3)bind/call/apply改变this指向

补充:bind/call/apply使用方法

const target={}fn.call(target, 'arg1', 'arg2')
fn.apply(target,['arg1','arg2'])
fn.bind(target, 'arg1', 'arg2')()

示例一

function greet() {console.log(`Hello, ${this.name}`);
}const person = { name: 'Alice' };// 使用 call 明确指定 this
greet.call(person);  // 输出:Hello, Alice

示例二

function greet(city, country) {console.log(`Hello, ${this.name} from ${city}, ${country}`);
}const person = { name: 'Bob' };// 使用 apply,参数是数组
greet.apply(person, ['New York', 'USA']);  // 输出:Hello, Bob from New York, USA

示例三

function greet() {console.log(`Hello, ${this.name}`);
}const person = { name: 'Charlie' };// 使用 bind 创建一个新的函数
const boundGreet = greet.bind(person)();// 输出:Hello, Charlie

  (4)构造函数和this

function Foo(){this.bar='hist'
}const instance=new Foo()
console.log(instance.bar);//hist

new操作符调用构造函数做了什么?

  • 创建一个新的对象
  • 将构造函数的this指向这个新对象
  • 为这个对象添加属性、方法等
  • 最终返回新对象

下面是构造函数中出现显示return的情况,分为两种场景:

function Foo() {this.user = 'hist'const o = {}return o
}const instance = new Foo()
console.log(instance.user);//undefined

 将会输出 undefined,此时 instance 是返回的空对象 o。

function Foo() {this.user = 'hist';return 1;
}const instance = new Foo();
console.log(instance.user);//hist

 将会输出 hist,也就是说此时 instance 是返回的目标对象实例 this。

结论:如果在构造函数中显式返回一个值,且返回的是一个对象,那么 this 就指向这个返回的对象;如果返回的不是一个对象,那么 this 仍然指向实例。

   (5)箭头函数中的this指向

箭头函数和普通函数有一个重要的区别:箭头函数不会有自己的 this,它会继承外部上下文的 this。

const foo = {fn: function () {setTimeout(function () {console.log(this);});},
};
foo.fn();//window

this 出现在 setTimeout() 中的匿名函数里,因此 this 指向 window 对象

const foo = {fn: function () {setTimeout(() => {console.log(this);});},
};foo.fn();//{fn: ƒ}
  • 在 foo.fn() 调用时,this 在 fn 方法内指向 foo 对象。
  • setTimeout 中的箭头函数继承了外部的 this,也就是 foo 对象。

(6)this优先级

通过 call、apply、bind、new 对 this 绑定的情况称为显式绑定

根据调用关系确定的 this 指向称为隐式绑定

function foo(a) {console.log(this.a);
}const obj1 = {a: 1,foo: foo,
};const obj2 = {a: 2,foo: foo,
};obj1.foo.call(obj2); //2
obj2.foo.call(obj1); //1

call、apply 的显式绑定一般来说优先级更高

function foo(a) {this.a = a;
}const obj1 = {};
var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a);

上述代码通过 bind,将 bar 函数中的 this 绑定为 obj1 对象。执行 bar(2) 后,obj1.a 值为 2。即经过 bar(2) 执行后,obj1 对象为:{a: 2}。

当再使用 bar 作为构造函数时:

var baz = new bar(3)
console.log(baz.a)//3

将会输出 3。我们看 bar 函数本身是通过 bind 方法构造的函数,其内部已经将 this 绑定为 obj1,它再作为构造函数,通过 new 调用时,返回的实例已经与 obj1 解绑。 也就是说:new 绑定修改了 bind 绑定中的 this,因此 new 绑定的优先级比显式 bind 绑定更高。

function foo() {return (a) => {console.log(this.a);};
}const obj1 = {a: 1,
};const obj2 = {a: 2,
};const bar = foo.call(obj1);
bar.call(obj2);//1

由于 foo() 的 this 绑定到 obj1,bar(引用箭头函数)的 this 也会绑定到 obj1,箭头函数的绑定无法被修改。

var a = 123;const foo = () => (a) => {console.log(this.a);};const obj1 = {a: 2,};const obj2 = {a: 3,};const bar = foo.call(obj1);console.log(bar.call(obj2));//123

箭头函数的绑定无法被修改,foo的执行上下文是window

如果将第一处的var a = 123;改为const a = 123;

答案将会输出为 undefined,原因是因为使用 const 声明的变量不会挂载到 window 全局对象当中

相关文章:

JS中this的值详细讲解以及面试指向练习

this 的值取决于它出现的上下文:函数、类或全局。 在函数内部,this 的值取决于函数如何被调用,this 是语言在函数体被执行时为你创建的绑定 对于典型的函数,this 的值是函数被访问的对象。换句话说,如果函数调用的形…...

显示浮动式窗口的方法

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了AlertDialog Widget相关的内容,本章回中将介绍BottomSheet Widget.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的BottomSheet是一种弹出式窗口,和上一章回中介绍的AlertDialog类似,但是也…...

FireFox火狐浏览器企业策略禁止更新

一直在用火狐浏览器,但是经常提示更新,进入浏览器右上角就弹出提示,比较烦。多方寻找,一直没有找到合适的方案,毕竟官方没有给出禁用检查更新的选项,甚至about:config里都没有。 最终找到了通过企业策略控…...

C++类的运算符重载

目标 让自定义的类直接使用运算符运算 代码 头文件及类定义 #include <iostream>using namespace std; class Complex {int rel;int vir; public:void show(){cout <<"("<<this->rel<<","<<this->vir<<&quo…...

泷羽Sec学习笔记-zmap搭建炮台

zmap搭建炮台 zmap扫描环境&#xff1a;kali-linux 先更新软件库 sudo apt update 下载zmap sudo apt install zmap 开始扫描(需要root权限) sudo zmap -p 80 -o raw_ips.txt 代码解析&#xff1a; sudo&#xff1a;以超级用户&#xff08;管理员&#xff09;权限运行…...

分析M0G突破后急剧下跌内因,x.game阐述不利面延续多久

MOG最新消息显示&#xff0c;美国唐纳德-的一则声明公开表示支持一种基于以太坊网络ERC-20代币标准的病毒式meme代币——Mog Coin&#xff08;MOG&#xff09;&#xff0c;这一消息迅速发酵。然而&#xff0c;令人意想不到的是&#xff0c;在这位全球知名政治人物的背书之后&am…...

网络爬虫全解析

一、网络爬虫基础要点 &#xff08;一&#xff09;爬虫原理 目标确定&#xff1a;明确需要抓取数据的网站或网页范围&#xff0c;例如针对特定电商平台抓取商品信息&#xff0c;或聚焦新闻网站获取新闻报道内容&#xff0c;要考量数据的价值与用途。URL 解析&#xff1a;理解网…...

《孤岛惊魂4》无法启动提示缺少“msvcp100.dll”快速修复方法!

《孤岛惊魂4》缺少msvcp100.dll的解决之道 在探索《孤岛惊魂4》这款充满惊险与刺激的射击游戏时&#xff0c;玩家可能会遇到一些意外的障碍&#xff0c;其中之一便是“缺少msvcp100.dll”的错误提示。这个错误不仅让游戏无法正常启动&#xff0c;还可能让玩家对游戏的热情大打…...

GS-SLAM论文阅读--RGBDS-SLAM

前言 最近GS-SLAM领域的工作层出不穷&#xff0c;有很多不错的工作出现。接下来慢慢写一下相关博客。 文章目录 前言1.背景介绍2.关键内容2.1 3D多层次金字塔高斯喷溅2.2 紧密耦合多特征重构优化2.3总体流程 3.文章贡献4.个人思考 1.背景介绍 高保真重建是密集SLAM的关键。最…...

条件编译->enable_if和 if constexpr使用区别

enable_if 和 if constexpr 是 C 中用于控制编译或运行时条件的重要工具&#xff0c;它们各有不同的用途和使用场景。以下是它们的主要区别&#xff1a; 1. enable_if std::enable_if 是一个类型特征&#xff0c;用于在编译时根据条件选择类型。常用于模板元编程&#xff0c;…...

介绍一下CSS中伪类和伪元素的概念

一、伪类&#xff08;Pseudo - Classes&#xff09; 1. 定义 伪类是添加到选择器的关键字&#xff0c;用于定义元素的特殊状态。这些状态不是由文档树中的结构或属性来表示&#xff0c;而是基于用户行为&#xff08;如鼠标悬停&#xff09;、元素状态&#xff08;如被选中&am…...

【橘子ES】熔断器Circuit breaker

一、相关概念 我们在日常的开发中&#xff0c;关于服务之间的熔断操作似乎很常见&#xff0c;当请求超过了我们服务所认为可以承受的一个上限阈值的时候&#xff0c;我们为了保护服务不会被进一步的高负载压崩溃&#xff0c;我们有时候会选择熔断请求&#xff0c;此时服务不再…...

6.4 CPU性能分析--Intel处理器跟踪技术

Intel处理器跟踪PT技术是记录程序执行过程的技术&#xff0c;它把记录信息编码报文存到高压缩率的二进制文件中。该二进制文件结合每条指令的时间戳重建执行流。PT技术覆盖度大&#xff0c;开销小&#xff0c;有关开销的信息详见&#xff0c;主要用于性能问题的事后分析和根因定…...

期权懂|如何用第三方平台开通期权?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 如何用第三方平台开通期权&#xff1f; 如果不能满足常规的期权开户条件&#xff0c;可以考虑以下几种方法来尝试开户&#xff1a; 一、选择第三方平台&#xff1a; 通过网络搜…...

JS中const有没有变量提升

在JavaScript中&#xff0c;const 关键字用于声明一个只读的常量&#xff0c;其值在初始化后不能被重新赋值。关于变量提升&#xff08;Hoisting&#xff09;&#xff0c;它是JavaScript中一个重要的概念&#xff0c;指的是无论变量或函数声明在何处&#xff0c;它们都会被“提…...

Axure RP全面介绍:功能、应用与中文替代方案

Axure RP是一款功能强大的原型设计工具&#xff0c;它被广泛应用于网页和移动应用的设计领域。Axure RP集成了设计、原型制作和文档管理&#xff0c;为产品管理人员、设计师和开发人员提供了一个综合的平台。让我们一步步了解Axure的基本功能、使用技巧以及中文支持平台——“在…...

WordPress用户首次登录强制修改密码

有些企业网站要求很高&#xff0c;比如用户首次登录强制要求修改密码&#xff0c;这里提供一段代码&#xff0c;用于实现强制修改密码供参考。 通过代码可以实现&#xff0c;用户正常注册或者管理员在后台添加用户时&#xff0c;会添加首次登录标记&#xff0c;用户首次登录后会…...

AI开源南京分享会回顾录

AI 开源南京分享会&#xff0c;已于2024年11月30日下午在国浩律师&#xff08;南京&#xff09;事务所5楼会议厅成功举办。此次活动由 KCC南京、PowerData、RISC-Verse 联合主办&#xff0c;国浩律师&#xff08;南京&#xff09;事务所协办。 活动以“开源视角的 AI 对话”为主…...

基于事件驱动的websocket简单实现

websocket的实现 什么是websocket&#xff1f; WebSocket 是一种网络通信协议&#xff0c;旨在为客户端和服务器之间提供全双工、实时的通信通道。它是在 HTML5 规范中引入的&#xff0c;可以让浏览器与服务器进行持久化连接&#xff0c;以便实现低延迟的数据交换。 WebSock…...

【leetcode100】反转链表

1、题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 2、初始思路 2.1 思路 # Definition for singly-linked list. # class ListNode: # …...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...