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 全局对象当中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/62863.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年河南省高等职业教育技能大赛 大数据分析与应用赛项竞赛方案

2024年河南省高等职业教育技能大赛 大数据分析与应用赛项竞赛方案 一、赛项名称 赛项名称:大数据分析与应用 赛项编号:HN033 赛项组别:专业核心基本技能赛项 专业大类:电子与信息等 竞赛形式:学生组(团体赛…

vue绕过rules自定义编写动态校验

今天犯了个低级错误,虽然走了很多弯路,但这个过程还是值得记录一下 例子如下,有两个输入框: 第一个是套餐选择下拉框,可以下拉选择三个内容 第二个要根据上面的套餐选择三个选项来决定怎么显示,使用v-if&…

数字化招聘系统如何帮助企业实现招聘效率翻倍提升?

众所周知,传统的招聘方式已经难以满足现代企业对人才的需求,而数字化招聘系统的出现,为企业提供了全新的解决方案。通过数字化招聘系统,企业可以自动化处理繁琐的招聘流程,快速筛选合适的候选人,从而大幅提…

短视频矩阵源码开发部署全流程解析

在当今的数字化时代,短视频已成为人们娱乐、学习和社交的重要方式。短视频矩阵系统的开发与部署,对于希望在这一领域脱颖而出的企业和个人而言,至关重要。本文将详细阐述短视频矩阵源码的开发与部署流程,并附上部分源代码示例&…

华为云云原生中间件DCS DMS 通过中国信通院与全球IPv6测试中心双重能力检测

近日,中国信息通信研究院(以下简称“中国信通院”)与全球IPv6测试中心相继宣布,华为云的分布式缓存服务(Distributed Cache Service,简称DCS)和分布式消息服务(Distributed Message …

关闭WPS在线功能资源和功能推荐

Kingsoft\WPS Office\12.1.0.18912\office6 选择 【高级】 点击 【确定】

Polars数据聚合与旋转实战教程

在这篇博文中,我们的目标是解决数据爱好者提出的一个常见问题:如何有效地从Polars DataFrame中创建汇总视图,以便在不同时间段或类别之间轻松进行比较。我们将使用一个实际的数据集示例来探索实现这一目标的各种方法。 Polars简介 Polars 是…

2024154读书笔记|《带着诗歌上街去》——我不长叶子,不开花,也不必要什么结果

2024154读书笔记|《带着诗歌上街去》——我不长叶子🌿,不开花🌼,也不必要什么结果 《带着诗歌上街去》作者隔花人,作者很有巧思,在拍摄的照片上做诗,诗不是很有感觉,但是在墙上、风景…

建立基于TCP的客户端和服务端

函数介绍: 1.socket() 作用:创建套接字 domain: AF_INET:IPv4 Internet 协议族。AF_INET6:IPv6 Internet 协议族。AF_UNIX:Unix 域协议族,用于在同一台主机上的进程间通信。 type: SOCK_STREAM&#xff1a…

CNCF云原生生态版图-分类指南(三)- 运行时

CNCF云原生生态版图-分类指南(三)- 运行时 CNCF云原生生态版图-分类指南三、运行时(Runtime)(一)云原生存储(Cloud Native Storage)1. 是什么?2. 解决什么问题&#xff1…

机器学习经典算法

机器学习经典算法学习和分享。 k近邻算法 线性回归 梯度下降法 PCA主成分分析法 多项式回归 逻辑回归 支撑向量机SVM 决策树 随机森林 评价分类指标

MVC基础——市场管理系统(三)Clean Architecture

文章目录 项目地址五、Clean Architecture5.1 user cage driven5.1.1创建CoreBusiness 5.2 创建UseCases5.2.1 创建CategoriesUseCases1. 创建VeiwCategoriesUseCase获取所有Cagegory 5.2.2. 实现ICategoryRepository接口3. 实现获取所有Category的方法4. 实现获取一个Cagegory…

手机上和电脑上都能观看的翻页电子书是如何制作的?

想知道手机上和电脑上都能观看的翻页电子书是都是如何制作的? 想知道这样的电子书是怎样呈现出来的? 那收藏这篇文章,我来跟大家说说该如何实现。 操作方法 一、登录FLBOOK 二、开始制作,有多种创建方式,分别是&…

ABAP时间戳与日期时间转换及时区处理

一、时间戳转换为日期时间 1. 基本转换 CONVERT TIME STAMP <fs_back>-lastchangedatetime TIME ZONE sy-zonloINTO DATE DATA(lv_date)TIME DATA(lv_time).2. 解决8小时时差问题的方案 方案1&#xff1a;直接使用UTC时区&#xff08;推荐&#xff09; CONVERT TIME …

Java 实现给pdf文件指定位置盖章功能

Java 实现给pdf文件指定位置盖章功能 开发中遇到一个需求, 需要给用户上传的的pdf文件, 指定位置上盖公章的功能, 经过调研和对比, 最终确定实现思路. 这里是使用pdf文件中的关键字进行章子的定位, 之所以这样考虑是因为如果直接写死坐标的话, 可能会出现因pdf大小, 缩放, 盖章…

ASP.NET Core API + MySql

环境 数据库&#xff1a; mysql8.0 后端&#xff1a; vs2022 ASP.NET Core API .net 8 前端&#xff1a; Hbuilderx bootstrap 5.3.0 jquery v3.7.1 bootstrap-table 1.23.5 创建项目 添加资源包 AutoMapper Microsoft.EntityFrameworkCore.Tools 8.0.0 Pomelo.EntityFramew…

RFDiffusion 计算键角函数get_ang解读

get_ang 函数&#xff08;kinematics.py包中&#xff09;计算三组原子 a,b,c 所形成的平面角&#xff08;planar angle&#xff09;&#xff0c;即 b 为顶点&#xff0c; a,b,c 所确定的角度。 源代码&#xff1a; def get_ang(a, b, c):"""calculate planar …

Bananna Pi开源社区联合矽昌通信打造开源的低成本Wifi5路由器

香蕉派 BPI-Wifi5 路由器采用矽昌SF19A2890S2芯片方案设计。它是一款高性能无线路由器&#xff0c;适用于小微企业、家庭和其他网络环境。Banana Pi开源社区提供整体解决方案。所有代码开源&#xff0c;用户可以在上面自由开发自己的应用。 Banana Pi wifi5 路由器github代码: …

图像融合算法笔记2024 CDTNet

目录 ControlCom-Image-Composition CDTNet-High-Resolution-Image-Harmonization 依赖项: trilinear 推理代码ok: ControlCom-Image-Composition diffusesion https://github.com/bcmi/ControlCom-Image-Composition CDTNet-High-Resolution-Image-Harmonization

item2 for macos

安装Item2 brew install iterm2 查看终端类型 cat /etc/shells Mac OS X 10.15 已经将默认的shell从Bash换成了zsh&#xff0c;所以不用安装&#xff0c;10.15以前的可以使用下面的命令进行安装 brew install zsh 安装Oh My ZSH # curl sh -c "$(curl -fsSL https://ra…