面试官:JS中this指向哪儿?你是如何确定this的?

前语

只要你踏入JavaScript 的世界,那么你一定会遇到 this 要害词。有许多人所 thisJavaScript 中最杂乱的东西之一,也有人说 this 其实很简略……可是事实的确,有许多工作了好多年的小伙伴,在 this 指向问题上也常常出现过错。

总归,咱们本篇文章的目的便是为javascript百炼成仙免费阅读了让咱们彻底了解 this,遇到 this 不再惧怕!

1.为什么要有 this?

已然 this 这么多小伙伴都觉得难,那为什么还要运用javascript它呢?依据哲学思想:存在即合理。已然 this 被提了出来,那么它肯定协助咱们处理了一些问题,又或许提升了开发效率。

咱们先运用测试用例一句比较官方的一句话来总结 this 处理了什么问题。

较为官方的解说:

this 被主动界说在所有前端开发函数的效果域中,它提供了一种更好的办法来“前端开发工程师工作内容隐式”的传递目前端开发标引证,这样使得咱们的 API 设计或许函数变得愈加简练,并且还更简略复用。

看了上面那样官方的一段话是不是感觉脑子变成了一团浆糊,没看懂要紧。咱们可以结合一段代码再来了解。

代码如下:

function say() {
  console.log("你好!", this.name);
}
let person1 = {
  name: '小猪讲堂'
}
let person2 = {
  name: '张三'
}
say.call(person1); // 你好! 小猪讲堂
say.call(person2); // 你好! 张三

上面这段代码十分简前端开发需要掌握什么技术略,咱们在函数内部运用了 person1persjavascriptonjavascriptdownload2 目标中的那么特色,可是咱们的函数实践上并没有接纳参数,而是调用 this 隐式的运用了 name 特色,即隐式运用上下文目标测试nameJavaScript咱们使用了 call 办法将函数内部的 this 指向了 person1person2,这浏览器的历史使得咱们的函数变得简练且简略复用。

咱们想一想,假如咱们没有 this,那么咱们就需求显式的将上下文目标传入函数,即显式传入 person1person2 目标。

代码如下:

function say(context) {
  console.log("你好!", context.name);
}
let person1 = {
  name: '小猪讲堂'
}
let person2 = {
  name: '张三'
}
say(person1); // 你好! 小猪讲堂
say(person2); // 你好! 张三

上段代码中没有运用 this,所以咱们直接显式的将上下文目标传入了函数,尽管现在代javascript高级程序设计码看起来不杂乱,测试你适合学心理学吗可是随着咱们的业务逻辑逐步浏览器推荐杂乱,或许说函数变得杂乱起来,那么咱们传入的 context 上下文目标上下文什么意思只会让代码变得越来越混乱。

可是假如咱们运用了 this,便不会这样,条件是咱们需求清楚的知道 this 指代的上下文目标是谁。

当然,假如你对上面的代码不太了解,别急,慢慢来,看完本篇文章!

2.this 过错的了解

关于许多初学者,刚开始接触到 this 要害词时,常常踏入许多上下文什么意思误区。很大一部分原因的确是由于上下文图 this 有许多坑,可是终究原因仍是没有搞懂 this 的指向原理。这儿咱们举出初学者浏览器历史上的痕迹在哪里常见的 this前端开发有前景吗 误区,也是许多面试题里边常常喜爱挖坑的当地。

2.1 this 指向函数自身?

这一javascript什么意思个误区是许上下文字间距怎么调多初学者都会踏入的,毕竟 this 要害词英译过来便是“这儿”的意思,咱们在函数里边运用 this,理所当然任务 this 指代的上下文什么意思是当前函数。

可是事实果真如此吗?咱们一同来看一段代码。

代码如下:

function say(num) {
  console.log("函数履行:", num);
  this.count++;
}
say.count = 0;
say(1); // 函数履行:1
say(2); // 函数履行:2
say(3); // 函数履行:3
console.log(say.count); // 0

上段代码中咱们给 say 函数添加了一个 count 特色,由于在 JS 中函数也是一个目标。然后咱们履行了 3 次函数,并且每次履行都调用了 count++

javascript高级程序设计如咱们认为 this 指向的是函数javascript:void(0)自身,那么this.count+上下文英语+履行的便是say.count,所以按理来说咱们终究打印 say.count 成果应该是3,可是浏览器的历史成果却是0。阐明thisJavaScript.count并不是say.count前端开发

所以咱们终究得出结论:say 函数内部的 this 并不履行函数自身!

那么咱们上段代码中的 this.count 是哪里的 count 呢?实践上履行this.count+上下文字间距怎么调+的时分,会声明一个大局变量 count,至于为什么,本篇文章和后面会解说。

打印 count:

console.log(say.count); // 0
console.log(count); // NaN

2.2 this 效果域问题

效果域也是 JS浏览器怎么打开网站比较难的知浏览器下载识点之一了,咱们这儿不会展浏览器历史记录设置开说效果域测试英文问题。咱们只给出 this 指向在效果域方面的误区,这个误浏览器网站删除了怎么恢复区许多初学者乃至前端开发和后端开发有什么区别好多年经验的开发者也会javascript什么意思踏入此误区。

咱们可以先来看一段十分经典的代码:

function foo() {
  var a = 2;
  this.bar();
}
function bar() {  
  console.log(this.a);
}
foo(); // undefined

上段代码中咱们在 foo 函数内部运用 this 调用了 bar 函数,然后在 bar 函数内部测试工程师打印 a 变量,假如咱们依照效果域链的思想考虑的话,此刻的 a 变量按道理是可以读取到的,可是事实却是 undefined

形成上述问题的原因有多个,其间有一个便是 this 在任何状况下都JavaScript不指向函数的词法效果域,上段代码就运用运用 thisfoobar 函数的词法效果域测试手机是否被监控联通,这是不可行的。

至于词法效果测试手机是否被监控域是什么,这儿不展开说,需求咱们自行下去学习,简略来说词法效果域是由你在写代码时将变量和块效果域浏览器下载写在哪来决定的。

3.this 的界说

看了前面两章节,咱们大约能了解 this 是什么?它其实便是一个履行上下文中的一个特色,咱们也可以简略的把 this 当作一个目标,只不过该目标指向哪儿是在函数调用的时分确浏览器历史记录设置认的。

咱们简略总结一下 this 的特色:

  • this 是在运行时绑定的,不是在编写时联系上下文绑定
  • this 的绑定与javascript高级程序设计函数的声明和方位没有任何联系
  • 函数在调用时,会创立一个履行上下文,this 便是这个履行上下文中的一个特色,在函数浏览器怎么打开网站履行的时分可以用到 this浏览器的历史记录在哪所以 this 是在函数调用的前端开发需要学什么时分确认绑定联系的,也便是运行时。

所以,总结出来大约就一句话:

this 便是一个目标,this 是在函数被调用时发生的绑定,它javascript百炼成仙免费阅读指向什么完全取决于函数在哪里被调用。

4.this 绑定规矩

到这儿咱们知道了 this 的绑定是在函数调用的时分确认的,以及 this 不指向函数自身javascript百炼成仙等等问题。那么,函数在某个方位被调用时,咱们怎么确认 this 该绑定到哪里呢?这个时分咱们就需求一些绑定规矩来协助咱们清晰 this 绑定到哪里了,当然,想要运用绑定规矩的条件是,咱们需求知道函数的调用方位javascript面试题

有些状况下,函数的调用方位咱们可以直接观察测试工程师出来,可是有些状况稍显杂乱,这个时分咱们就需求凭借调用栈来来分析出函数的实践调用方位了。

咱们可以经过浏览器来检查调用栈,简略测试抑郁程度的问卷来说调用栈就相当于函数的调用链,和效果域链有异曲同工之妙,只是咱们直接看代码分测试用例析或许不太简略执行上下文。所以咱们可以经过打断点的办法,然后凭借浏览器来检查调用栈,如下图所示:

面试官:JS中this指向哪儿?你是怎么确认this的?
调用栈的详细用法还需求咱们下来仔前端开发工资一般多少细学习。

接下上下文英语来就来学测试英文习详细的 this 绑定规矩。

4.1 默许绑定

咱们比较常见的一种函数调用类型便是独立函数的调用,形如f测试oo测试英文()等。前端开发工资一般多少这个浏览器的历史记录在哪时分的 this 绑定便是选用的默许绑定规矩。

代码如下:

var name = '小猪讲堂';
function foo(){
  console.log(this) // Window{}
  console.log(this.name) // 小猪讲堂
}
foo(); // 小猪讲堂

上段浏览器历史记录设置代码十分简略,咱们在大局效果域中界说了一个变量name,然后咱们在函联系上下文foo 中运用th测试抑郁程度的问卷is.name前端开发入门薪水输出的成果便是大局变上下文英语name,这阐明咱们 this 指向了大局效果域,也便是说 this 绑定到了 wind测试你适合学心理学吗ow 目标上。

输出成果:

面试官:JS中this指向哪儿?你是怎么确认this的?

面试官:JS中this指向哪儿?你是怎么确认this的?
函数的这种调用办法就被称为默许绑测试你的自卑程度定,默许绑定规矩下的 this 指向大局目标。

咱们可以给默许绑定进程上下文给个界javascript百炼成仙说:

当函数不带用任何修饰进行调用时,此刻 this 的绑定便是默许绑定javascript高级程序设计规矩,this 指向大联系上下文局目标。

留意:

let变量声明不会绑定在window上面,只有var声明的才会,这是需求留意的。除此之外,严厉方法下上段代码的 thisun上下文字间距怎么调defined,比方下面这段代码:

var name = '小猪讲堂';
function foo(){
  'use strict'
  console.log(this.name)
}
foo(); // Uncaught TypeError: Cannot read properties of undefined (reading 'name')

从上段代上下文字间距怎么调码可以看出,默许绑定规矩下,this 绑定到了大局目标,当然这与函数调用方位有关。可是严厉方法下,this 的绑定与函数调用方位无关。

4.2 隐式绑定

前面的默许绑定规矩很好了解,由于咱们的函数履行上下文便是大局效上下文语境果域,this 自然而然绑定到了大局目标上。

独立函数的调用咱们可以直接看出履行上下文在哪里,但假如不是独立函数调用,比方下面代码。

代码如下:测试

function foo() {
  console.log(this.name) // 小猪讲堂
}
let obj = {
  name: '小猪讲堂',
  foo: foo
}
obj.foo();

上段代码咱们在 obj 目标中引证了函数 foo,然后咱们运用 obj.foo(函数别名)的办法调用了该函数,此刻不是独立函数调用,咱们不能运用默许绑定规矩。

此刻 this 的绑定规矩称为隐式绑定规矩,由于咱们不能直接看出函数的调用方位,它的实践调用方位在 obj 目标里边,调用 foo 时,它的履行上下文浏览器怎么打开网站目标为 obj 目标,所以 this 将会被绑定到 obj 目标上,所以咱们函数中的 th前端开发有前景吗is.name 其实便是obj.name。这便是咱们的隐式绑定联系上下文规矩。前端开发和后端开发有什么区别

留意:

假如咱们调用函数测试你适合学心理学吗时有多个引证调用,比方obj1.obj2.foo()。这个时分函数 foo 中的 this 指向哪儿呢?前端开发有前景吗其实不管引证链上下文字间距怎么调多长,this 的绑定都由最顶层调用方位确认,即obj1.obj2.foo()this 仍是绑定带 obj2

执行上下文式绑定中 thi浏览器历史上的痕迹在哪里s 丢掉

在隐式上下文图绑定规矩中,咱们认为谁调用了函数,t浏览器his 就绑定谁,比方 obj.foothis 就绑定到 obj,可是有一些状况比较特别,即便选用的隐式绑定规矩,可是前端开发软件 this 并没有依照咱们的想法去绑定,这便是所谓的隐式绑定 this 丢掉,常见于回调函数中。

代码如下:测试

function foo() {
  console.log(this.name) // 小猪讲堂
}
function doFoo(fn) {
  fn(); // 函数调用方位
}
let obj = {
  name: '张三',
  foo: foo
}
let name = '小猪讲堂';
doFoo(obj.foo); // 小猪讲堂

上段代码中咱们很简略会以为 foo 绑定的 thisobj 目标,由进程上下文于咱们运用了 obj.foo 的办法,这种办法便是遵循隐式绑浏览器推荐定规矩。可是事实上 this 却绑定到了大局目标上去,这是由于咱们在 doFoo 函数中调用 fn 时,这儿才是函前端开发和后端开发有什么区别数的实践调用方位,此刻是独立函数调前端开发用,所以 this 指向了大前端开发和后端开发有什么区别局目标。

实践项目中咱们简略遇到这种问题的场景或许便是定时器了,比方下面的代码:

setTimeout(obj.foo, 100)

这种写法就很简略形成 this 丢掉。

4.3 显式绑定

前面咱们现已说了默许绑定和隐前端开发工资一般多少式绑定,其间隐式绑定咱们通常是以 obj.foo 这种方法来调用函数的,目的便是为了让 foothis 绑定到 obj 目标上。

这个时分,假前端开发工程师工作内容如咱们不想javascript高级程序设计经过javascript是干什么的 obj.foo 的方法调用函数,咱们想要很清晰的将函数的 this 绑定在某个目标上。那么可以运用 callapply 等办法,这便是所谓的显式绑定规矩。

代码如下:

function foo() {
  console.log(this.name) // 小猪讲堂
}
let obj = {
  name: '小猪讲堂',
}
foo.call(obj);

上段代码咱们使用 call 办法直接将 foo 函数内部的 this 指向了 obj 目标,这便是显式绑定。

尽管显式绑定让咱们很清楚的知道了函数中的 this 绑定到了哪个目标上,可是浏览器网站删除了怎么恢复它仍是无法结局浏览器历史上的痕迹在哪里咱们 thisjavascript权威指南 绑定丢掉的问题,就比方下面这种写法:

function foo() {
  console.log(this.name) // 小猪讲堂
}
function doFoo(fn) {
  fn(); // 函数调用方位
}
let obj = {
  name: '张三',
  foo: foo
}
let name = '小猪讲堂';
doFoo.call(obj, obj.foo); // 小猪讲堂

上段代码咱们尽管运用 call 来更改 this 绑定,可是终究成果却是没有用的。

尽管显式绑定自身不能处理 this 绑定丢掉的问题测试你的自卑程度,可是咱们可以经过变通的办法来处上下文什么意思理这个测试你的自卑程度问题,也被称作硬绑定

硬绑定:

function foo() {
  console.log(this.name) // 小猪讲堂
}
function doFoo(fn) {
  fn(); // 函数调用方位
}
let obj = {
  name: '张三',
}
let bar = function () {
  foo.call(obj)
}
let name = '小猪讲堂';
doFoo(bar); // 张三
setTimeout(bar, 100); // 张三

其实思路也比较简略,出现 this 绑定丢掉原因无非便是咱们传入的回调函数在被履行时,this 绑定规矩变为了默许绑定,那么为了处理这个问题,前端开发软件咱们无妨在封装一个函数,将 foo 函数的 this 显式绑定到 obj 目标上去即可。

这儿提一点,下面写法是过错的:

doFoo(foo.call(obj));

由于回调函数是在 doFoo 里边履行的,上面的写法相当于 foo 函数当即履行了。

弥补:

其实咱们的 bind 函数上下文什么意思便是一个硬绑定,咱们想一想,bind 函数是不是创立一个新的函数,然后将 this 指定,是不是就和咱们下面这段代码执行上下文的效果一样。

let bar = function () {
  foo.call(obj)
}
// bind 方法
let bar = foo.bind(obj)

4.4 new 绑定

new 要害词相信咱们都知道或许运用过吧,测试手机是否被监控这便是咱们将要将的第 4this 绑定,叫做 new 绑定。

想要知道 new 绑定规矩,咱们就很有必要知道一个当咱们 new 一个目标的时分做了什么,或许说 new 要害词会做哪些操作。咱们这儿简略总结一下,详细的 new 的进程还需求咱们自行下来好好学学。

运用 new 来调用函数时,会履行下面操作:

  • 创立一个全新的目标
  • 浏览器的历史记录在哪个新目标会被履行原型连接
  • 这个新目标会绑定到函数调用的 this
  • 假如函数没有返回其它目标,那么 new 表达式种的函数调用会主动返回这个新目标

咱们可以看到 new 的操作中就有 this 的绑定,咱们在浏览器历史上的痕迹在哪里来看看代码。上下文英语

代码如下:

function foo(name) {
  this.name = name;
}
let bar = new foo('小猪讲堂');
console.log(bar.name); // 小猪讲堂

上段代码咱们运用 new 要害词调用了 fojavascript百炼成仙o 函数,上下文语境咱们留意这不是默许调用规矩,这是 new 绑定规矩。

5.优先级

前面咱们总结了测试仪 4 条 this 绑定的规矩,在大多数状况下咱们只需求找到函数的调用方位,然后再判浏览器数据如何恢复别选用哪条 this 绑定规矩,终究确认 this 绑定。

咱们这儿进程上下文可以先简略总结一下 4 条规矩以及 this 绑定确认流程。

this 绑定确认流程:

先确认函数调用方位,然后确认运用哪条规矩,然后依据规矩确认 this 绑定。

this 绑定规矩:

  • 默许绑定:this 绑定到大局目标
  • 隐式绑定:一般绑定到调用目标,如 obj.foo 绑定到 obj
  • 显式绑定:经过 callapply 指定 this 绑定到哪里
    • 硬绑定:运用 bind 函数
  • new 绑定:运用 new 要害词,绑定到当前函数目标

可以看到,咱们确认 this 绑定的时分有 4 条规矩,在通常状况下,咱们可以依前端开发入门薪水据这 4 条规矩来判别出 this 的绑定。可是有时分某个函数的调用方位对应了多个绑定规矩,这个时分咱们该选用哪一条规上下文字间距怎么调矩来确认 this 绑定呢?这个时分就需求清晰每一条绑定规矩的优先级了!

首要咱们要清晰的式默许绑定规矩的优先级是最低的,所以咱们考虑的时分暂时不考虑默许绑定规矩。

5.1 隐式绑定与显式绑定

假如函测试抑郁症的20道题数调用的时分出现了隐式绑定和显式绑定,那么详细选用哪一个规矩,咱们经过代码来试验一下。

代码如下:

function foo(){
  console.log(this.name);
}
let obj1 = {
  name: '小猪讲堂',
  foo: foo
}
let obj2 = {
  name: '李四',
  foo: foo
}
obj1.foo(); // 小猪讲堂
obj2.foo(); // 李四
obj1.foo.call(obj2); // 李四
obj2.foo.call(obj1); // 小猪讲堂

上段代码中咱们触及到了两种 this 绑定,obj浏览器的历史.foo 为隐式绑定,this浏览器的历史记录在哪 绑定给 obj 目标,而 foo.call(obj)为显现绑定,this 绑定给 obj 目标。

从上段代码看出,当两个绑定规矩都存在的时分,咱们选用的是显式绑定规矩。

总结:

显式绑定 > 隐浏览器历史上的痕迹在哪里式绑定

5.2 new 绑定与隐式绑定

接下来咱们看看 new 绑定与隐式绑定的优先级。

代码如下:

function foo(name) {
  this.name = name;
}
let obj1 = {
  foo: foo
}
obj1.foo('小猪讲堂');
let bar = new obj1.foo("张三");
console.log(obj1.name); // 小猪讲堂
console.log(bar.name); // 张三

上段代码中在在运用 new 要害词浏览器怎么打开网站的时分又运用了 obj1.foo 隐式绑定,可是终究成果 this 并没有绑定到 obj1 目标上,所以隐式绑定优先级低于 new 绑定。

总结:

隐式绑定 < new 绑定

5.3 显式绑定与 new 绑定

接下来咱们比较显式绑定与 new 绑定规矩,可是咱们 new测试抑郁程度的问卷定与显式绑定的 call浏览器的历史记录在哪、apply 办法不能一同运用,所以咱们无法经过 new foo.前端开发软件call(前端开发obj)来进行测试

可是咱们前面解说javascript百炼成仙免费阅读显式绑定的时分,提到一种绑定叫做硬绑定,它也是显式绑定中的一种,所以说咱们可以使用硬绑定与 new 绑定来进行比较。

代码如下:

function foo(name) {
  this.name = name;
}
let obj1 = {};
let bar = foo.bind(obj1);
bar('小猪讲堂');
console.log(obj1.name); // 小猪讲堂
let baz = new bar('张三');
console.log(obj1.name); // 小猪讲堂
console.log(baz.name); // 张三

上段代码中咱们把 obj 硬绑定到了 bar 上,然后咱javascript面试题们经过 new 绑定调用了函数,可是 obj1.name 仍是小猪讲堂,并没有改为张三,可是,咱们的 new 操作前端开发需要学什么修改了硬绑定(到 obj1 的)调用 bar 中的 this。由于运用了 new 绑定,咱们得到了新的 baz 目标,并且 baz.name 为张三。

总结:

new上下文语境 绑定 > 显式绑定,需求留意的是,new 操作时将 this 绑定到了新创立的联系上下文目标。

6.this 绑浏览器网站删除了怎么恢复定总结

到这儿,咱们基本上可以确认一个函数内部的 this 指向哪儿了,咱们这儿做出一些总结,以供在项目实践中判别 this 绑定。

this 绑定规矩优先级:

默许绑浏览器的历史记录在哪定 < 隐式绑定 < 显式绑定 < new 绑定

判别 this 终究指向,总体流程:

  1. 判别函数调用时是否运用了 new,即 new 绑定,假如运用了,则 thisjavascript面试题 绑定的是新创立的目标。
  2. 函数调用是否运用了 callapply 等显式绑定,或许硬绑定(bind),假如是的话,t前端开发工资一般多少his 指向指定的目标。
  3. 函数是否在某个上下文目标中调用,即隐式绑定,如 obj1.foo,假如是的话,this 指向绑定的那个上下文目标。
  4. 以上 3 点都不触及的话,则选用默许绑定,可是需求留意的是,在严厉方法下,默许绑定的 thisundefined前端开发是什么非严厉方法下绑定到大局目标。

结合上面的绑定优先级以及判别流程,咱们在一般的项目中以及可以判别出 this 指向哪儿了!

总结

this 绑定尽管是一个浏览器数据如何恢复比较难的知识点,可是咱们作为一个前端开发者,必需要学会怎么了解和运用它,由于它的确能给咱们带来许多的便利和优点。

当然,本篇文章只解说了最惯例的 this 绑定及原理,除此之外,this 绑定还有一些意外的状况测试抑郁症的20道题,这儿不做更多解说,感兴趣的小伙伴可以自行下来查询材料,比方说软绑定、直接引证等等。

总归,惯例判别如下:

  1. new 调用函数,绑定到新目标
  2. call 等调用,绑定到指定目标
  3. 由上下文目标功效,绑定到上下文目标
  4. 默许调用,绑定到大局目标或 und联系上下文efined

参考材料: 《你不知道的JavaScript》

我正在参与技javascript面试题能社区创作者签约方案招募活测试动,点击链接报上下文图名投稿。

发表评论

提供最优质的资源集合

立即查看 了解详情