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

this指哪去了

前言

但凡是前端的人应该都被this折磨过,不管是不会用还是用错都会造成很大的麻烦,不论是敲代码还是准备面试时候,都要复习好多次,这次记个笔记方便以后复习。

this的特点

官方解释:this 被自动定义在所有函数的作用域中,它提供了一种更好的方式来“隐式”的传递对象引用,这样使得我们的 API 设计或者函数变得更加简洁,而且还更容易复用。

简单的来讲就是为了在函数作用域内更方便的使用这个函数中的对象内容
例1:
在这里插入图片描述

这里的this就指向的是整体的类中,通过this可以访问类中的内容

例2:
在这里插入图片描述

person1person2是两个对象想用一个函数就动态的输出两个对象对应的值。
没有this之前可能想的是给say方法传递参数,但通过this.可以直接通过this.name,然后改变this的指向(call就是用来改变内容this的指向的)

上面这些可以让你很清晰的理解到this是干什莫的。

但是他this的难点不在这里。难点在于this指向的是什么地方。

this 就是一个对象,this 是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

常见的this指向

1.普通函数:指向window

在直接定义的普通函数中使用时,this指向的是window层面

let x = 1;
var y = 2;
function f(){
    console.log(this.x) 
    console.log(this.y) 
}
f();
//打印 :undefined
//2

首先f的执行环境为window,所以this指向windowthis.xthis.y等同于window.xwindow.y

那为什么this.x不是1呢?

var声明的y变量会被js引擎挂在到jswindow属性中,所以window.y是2。然而es6let声明的变量,不会被挂载到window属性中,而是会挂载到和Global(window)同级的Script中。this.x还是等同于window.x,但是由于window上没有x这个属性,所以就打印undefined了。、

2.对象方法:指向调用该方法的对象

根据该方法调用时所处的环境,决定指向

let obj1 ={
    x:1,
    f:function(){
        console.log(this.x)
    }
}
let obj2 ={
    x:2,
    f:obj1.f
}
obj1.f() //1
obj2.f()//2

第一个函数f在``obj1环境下执行,this指向obj1,所以this.x等同于obj1.x`,打印1。

我相信第一个大家都没问题,第二个就有点疑惑了,有人可能会这样想:obj2.f明明是调用obj1.ff的运行环境还在obj1中,应该打印1才是。
但是现在调用的这个方法上层是在obj2的环境中,指向的实际上是obj2的内容

因此,对象方法中this指向调用该方法的对象。注意:

如果我们调用函数时有多个引用调用,比如obj1.obj2.foo()。这个时候函数 foo 中的 this 指向哪儿呢?其实不管引用链多长,this 的绑定都由最顶层调用位置确定,即obj1.obj2.foo()this 还是绑定带 obj2

如果我们调用函数时有多个引用调用,比如obj1.obj2.foo()。这个时候函数 foo 中的 this 指向哪儿呢?其实不管引用链多长,this 的绑定都由最顶层调用位置确定,即obj1.obj2.foo()this 还是绑定带 obj1


作者:小猪课堂
链接:https://juejin.cn/post/7115390077353590792
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

3.构造函数:指向实例对象

function F(x){
    this.x=x
    this.f=function(){
        console.log(this.x)
    }
}
let fn = new F(2)
fn.f()//2

这里的this指向具体的实例对象,也就是fnfn中存在x属性:2,this.x也就是fn.x,输出2了。

4.绑定事件函数 :指向绑定事件的元素
<button>点击</button>
const btn = document.querySelector("button");
      btn.onclick = function () {
        console.log(this);
      };
//打印<button>点击</button>
5.回调函数

对于回调函数中的this对象。对于普通函数,this指向调用时所在的对象(即window对象)。对于箭头函数,this指向定义生效时所在的对象。

普通函数:

var id = 10;
function foo() {
     setTimeout(function () {
         console.log(this.id);
    }, 1000);
}
foo(); //10
foo.call({ id: 30 }); //10

上面都输出10,this指向window对象,原因是1s后,回调函数执行,此时回调函数所在对象为window

箭头函数:

对于普通函数来说,内部的this指向函数运行时所在的对象,但是这一点对箭头函数不成立。它没有自己的this对象,内部的this就是定义时上层作用域中的this。也就是说,箭头函数内部的this指向是固定的,相比之下,普通函数的this指向是可变的。

var id = 10;
function foo() {
     setTimeout(()=> {
        console.log(this.id);
    }, 1000);
}
foo();//10
foo.call({ id: 30 });//30

第一个回调函数输出10,定义时this就已经确认了指向,指向window

第二个回调函数输出30,与上述不同的是,这个回调函数的this在定义时已经重新指向为{id:30}这个对象了。

6.立即调用函数 :window
(function(){console.log(this)})() //window
注意严格模式下this
"use strict";
 console.log(this); //window
 function f() {
     console.log(this); //undefined
 }
 f();
  • 在严格模式下,在全局作用域中,this指向window对象
  • 在严格模式下,全局作用域函数中this等于undefined

相关文章:

  • 算法----二维区域和检索 - 矩阵不可变(Kotlin)
  • 向Visual Studio Code导入ST项目
  • ES6转为ES5 AST
  • 二分法查找方法
  • UE5物体旋转(蓝图版)
  • 【网络安全】SQL注入专题讲解
  • unordered_set、unordered_map的介绍+使用+比较
  • Leetcode139. 单词拆分
  • DRM系列(9)之drm_atomic_helper_commit
  • Unity入门03——Unity脚本
  • finally执行语句的注意和小陷阱
  • 【推荐系统->论文阅读】WideDeep模型
  • 【Node】cookie、sessionStorage、localStorage 与 身份认证
  • 把setting.xml放在conf和.m2目录的区别
  • OpenCV图像加载、显示与保存
  • Effective Java 笔记(一)
  • Java,console输出实时的转向GUI textbox
  • javascript从右向左截取指定位数字符的3种方法
  • JavaScript函数式编程(一)
  • js递归,无限分级树形折叠菜单
  • JS函数式编程 数组部分风格 ES6版
  • maven工程打包jar以及java jar命令的classpath使用
  • Swift 中的尾递归和蹦床
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • Vue组件定义
  • Yeoman_Bower_Grunt
  • 阿里研究院入选中国企业智库系统影响力榜
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 关于字符编码你应该知道的事情
  • 观察者模式实现非直接耦合
  • 检测对象或数组
  • 力扣(LeetCode)357
  • 排序算法学习笔记
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 线性表及其算法(java实现)
  • 学习笔记TF060:图像语音结合,看图说话
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 译有关态射的一切
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • FaaS 的简单实践
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #if 1...#endif
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • $NOIp2018$劝退记
  • (day 12)JavaScript学习笔记(数组3)
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (小白学Java)Java简介和基本配置
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转载)虚函数剖析
  • .Net 路由处理厉害了
  • .NET构架之我见
  • .net开发引用程序集提示没有强名称的解决办法
  • ::before和::after 常见的用法