js总结(二)--彻底理解js中this的指向,不必硬背。

2023-11-01

  首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉,那么接下来我会深入的探讨这个问题。

  为什么要学习this?如果你学过面向对象编程,那你肯定知道干什么用的,如果你没有学过,那么暂时可以不用看这篇文章,当然如果你有兴趣也可以看看,毕竟这是js中必须要掌握的东西。

例子1:

function a(){
    var user = "追梦子";
    console.log(this.user); //undefined
    console.log(this); //Window
}
a();

按照我们上面说的this最终指向的是调用它的对象,这里的函数a实际是被Window对象所点出来的,下面的代码就可以证明。

function a(){
    var user = "追梦子";
    console.log(this.user); //undefined
    console.log(this);  //Window
}
window.a();

和上面代码一样吧,其实alert也是window的一个属性,也是window点出来的。

例子2:

var o = {
    user:"追梦子",
    fn:function(){
        console.log(this.user);  //追梦子
    }
}
o.fn();

这里的this指向的是对象o,因为你调用这个fn是通过o.fn()执行的,那自然指向就是对象o,这里再次强调一点,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个。

 

其实例子1和例子2说的并不够准确,下面这个例子就可以推翻上面的理论。

如果要彻底的搞懂this必须看接下来的几个例子

本文出处:追梦子博客

例子3:

var o = {
    user:"追梦子",
    fn:function(){
        console.log(this.user); //追梦子
    }
}
window.o.fn();

 这段代码和上面的那段代码几乎是一样的,但是这里的this为什么不是指向window,如果按照上面的理论,最终this指向的是调用它的对象,这里先说个而外话,window是js中的全局对象,我们创建的变量实际上是给window添加属性,所以这里可以用window点o对象。

  这里先不解释为什么上面的那段代码this为什么没有指向window,我们再来看一段代码。

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //12
        }
    }
}
o.b.fn();

这里同样也是对象o点出来的,但是同样this并没有执行它,那你肯定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不准确,接下来我将补充一句话,我相信你就可以彻底的理解this的指向的问题。

  情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。

  情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。

  情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,例子3可以证明,如果不相信,那么接下来我们继续看几个例子。

var o = {
    a:10,
    b:{
        // a:12,
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

还有一种比较特殊的情况,例子4:

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();

这里this指向的是window,是不是有些蒙了?其实是因为你没有理解一句话,这句话同样至关重要。

  this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window,这和例子3是不一样的,例子3是直接执行了fn。

  this讲来讲去其实就是那么一回事,只不过在不同的情况下指向的会有些不同,上面的总结每个地方都有些小错误,也不能说是错误,而是在不同环境下情况就会有不同,所以我也没有办法一次解释清楚,只能你慢慢地的去体会。

 

构造函数版this:

function Fn(){
    this.user = "追梦子";
}
var a = new Fn();
console.log(a.user); //追梦子

 

这里之所以对象a可以点出函数Fn里面的user是因为new关键字可以改变this的指向,将这个this指向对象a,为什么我说a是对象,因为用了new关键字就是创建一个对象实例,理解这句话可以想想我们的例子3,我们这里用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a,那么为什么对象a中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。

  除了上面的这些以外,我们还可以自行改变this的指向,关于自行改变this的指向请看JavaScript中call,apply,bind方法的总结这篇文章,详细的说明了我们如何手动更改this的指向。

 

更新一个小问题当this碰到return时

function fn()  
{  
    this.user = '追梦子';  
    return {};  
}
var a = new fn;  
console.log(a.user); //undefined

再看一个

function fn()  
{  
    this.user = '追梦子';  
    return function(){};
}
var a = new fn;  
console.log(a.user); //undefined

再来

function fn()  
{  
    this.user = '追梦子';  
    return 1;
}
var a = new fn;  
console.log(a.user); //追梦子
function fn()  
{  
    this.user = '追梦子';  
    return undefined;
}
var a = new fn;  
console.log(a.user); //追梦子

什么意思呢?

  如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

function fn()  
{  
    this.user = '追梦子';  
    return undefined;
}
var a = new fn;  
console.log(a); //fn {user: "追梦子"}

还有一点就是虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。

function fn()  
{  
    this.user = '追梦子';  
    return null;
}
var a = new fn;  
console.log(a.user); //追梦子

知识点补充:

  1.在严格版中的默认的this不再是window,而是undefined。

  2.new操作符会改变函数this的指向问题,虽然我们上面讲解过了,但是并没有深入的讨论这个问题,网上也很少说,所以在这里有必要说一下。

function fn(){
    this.num = 1;
}
var a = new fn();
console.log(a.num); //1

 为什么this会指向a?首先new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。

2017-09-15 11:49:14

  注意: 当你new一个空对象的时候,js内部的实现并不一定是用的apply方法来改变this指向的,这里我只是打个比方而已.

  if (this === 动态的\可改变的) return true;

原链接:http://www.cnblogs.com/pssp/p/5216085.html

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

js总结(二)--彻底理解js中this的指向,不必硬背。 的相关文章

  • 第4章运算符

    第4章运算符 算术运算符 算术运算符主要用于数学运算 其可以连接运算符前后的两个数值或表达式 对数值或表达式进行加 减 乘 除 或 DIV 和取模 或 MOD 运算 加法与减法运算符 SELECT 100 100 0 100 0 100 5
  • 用Evolution收发livemail或hotmail的设置

    1 打开Evolution 选择 Edit gt Preferences gt Mail Accounts gt Add Name xxx live cn 或者是xxx hotmail com Full Name 自己的名字 Email A
  • 如何在PCB中导入LOGO

    我们在画PCB的时候有时候需要把一些图标或者图案弄在板子 这时候就需要用到导入LOGO 下面介绍怎么导入LOGO 第一步 导入LOGO前我们需要将PCB Logo Creator文件夹 也就是PCBLogoCreator PRJSCR 复制
  • OTA升级包的解释和升级方法

    OTA升级是什么意思 OTA升级就是某官方通过推送的方式将手机的固件升级通过推送信息的形势发送到用户的手机端 当用户收到推送信息以后即可从服务器联网下载升级包 这种升级方式即称之为OTA升级 OTA升级以后会不会删除手机端的联系人 应用程序
  • ubuntu18.04“软件与更新”中无附加驱动问题(已解决)

    刚安装完ubuntu18 04系统之后 想开启独显驱动 但是在 软件与更新 中不现实附加驱动 尝试过网络上其他方法但没有解决 这里我在 软件与更新 的 ubuntu软件 选项 左上角第一个 中 将 源代码 这个模块打开 便解决了问题 也许我
  • 农业知识图谱搭建和遇到的问题

    Agriculture KnowledgeGraph demo http ecnukg vicp io github https github com qq547276542 Agriculture KnowledgeGraph 本文基于华
  • JDBC——概念

    JDBC 概念 Java DataBase Connectivity Java 数据库连接 Java语言操作数据库 JDBC本质 其实是官方 sun公司 定义的一套操作所有关系型数据库的规则 即接口 各个数据库厂商去实现这套接口 提供数据库
  • vue中v-model双向绑定使用和原理

    1 给出双向绑定定义 vue中双向绑定是一个指令 v model 可以绑定一个响应式数据到视图 同时视图中变化能改变改值 2 双向绑定带来的好处 v model 是语法糖 默认情况下相当于 value 和 input 使用 v model
  • 性能测试-定义以及指标

    一 定义 性能测试是指通过自动化测试工具模拟多种正常 峰值 以及异常的负载情况下对系统各项性能指标进行的测试 负载测试 压力测试 容量测试都属于性能测试 负载测试 确定各种负载下系统的性能 目标是测试负载逐渐增加时各项指标的变化 压力测试
  • 【Python】输入输出与运算符

    目录 1 输入输出 1 1 和用户交互 1 2 通过控制台输出 1 3 通过控制台输入 2 运算符 2 1 算数运算符 2 2 关系运算符 2 3 逻辑运算符 2 4 赋值运算符 1 输入输出 1 1 和用户交互 程序需要和用户进行交互 用
  • GlusterFS云存储分布式文件系统 35课

    主要应用在集群系统中 具有很好的可扩展性 软件的结构设计良好 易于扩展和配置 通过各个模块的灵活搭配以得到针对性的解决方案 可解决以下问题 网络存储 联合存储 融合多个节点上的存储空间 冗余备份 大文件的负载均衡 分块 由于缺乏一些关键特性
  • MPChart的饼状图使用

    控件项目地址 https github com PhilJay MPAndroidChart 效果图 使用 1 导库 可以去下载jar包 下载地址 https github com PhilJay MPAndroidChart releas
  • R语言基础——R包的安装与使用

    R语言基础 R包的安装与使用 R包的安装 选择镜像站点 下载R包 使用函数library 来查看库里有哪些安装包 R包的使用 载入包 列出包的帮助文档 列出R包中所有包含的函数 列出R包中包含的数据集 移除加载的包 删除已安装的包 remo
  • 在Windows中搭建Python Web开发环境

    最近的一个外包项目 客户要求IE8 兼容 之前做自己的个人项目都是在Ubuntu下开发 然后在Chrome上跑一下就OK 完全没有管IE兼容性 这次不行了 得啃下这个骨头 测IE兼容有一款工具必不可少 那就是IETester 从IE5 5到
  • 常用算法之验证回文串

    今天给大家分享一道面试中经常碰到的简单算法题目 检测回文串 题目 给定一个字符串 验证它是否是回文串 只考虑字母和数字字符 可以忽略字母的大小写 示例1 输入 A man a plan a canal Panama 输出 true 示例2
  • vscode运行Python出现问题import cv2 ModuleNotFoundError: No module named 'cv2'

    import cv2 ModuleNotFoundError No module named cv2 vscode运行Python时出现问题 PS D bmi bmi project gt python demo py Traceback
  • 深港澳金融科技师(SHMFTTP)一级考试

    说明 个人整理的简易程序知识点笔记 比较好的地方是将刷题过程中遇到的题目 一起附在知识点后面了 结合题目对知识点的理解会更深 目录 一 金融标准化t35 50 一 伦理与职业素养t100 120 二 战略性新兴产业t1 20 正文 一 金融
  • 《Python进阶系列》二十三:解决线性规划和二次型规划问题的CVXOPT模块

    Python CVXOPT模块 Python中支持Convex Optimization 凸规划 的模块为CVXOPT 能够解决线性规划和二次型规划问题 其应用场景如SVM中的Hard Margin SVM Creating matrice

随机推荐

  • gtiee教程(三板斧)-------好东西我们一起来学习

    作者前言 这是我的gitee仓库 https gitee com qin laoda python exercises 有兴趣的小可爱们可以点进去看看 gtiee网址 https gitee com login 下面我来简单介绍一下gtie
  • 接口测试_无业务关联的单接口——注册功能测试设计

    接口文档大致如下 接口测试分析 案例设计 具体的案例省略 测试代码如下 encoding utf 8 import requests json os hashlib re def reg username password email ex
  • 创建第一个servlet项目(简单版创建)--详细图文教程

    Servlet 是一种实现动态页面的技术 是一组 Tomcat 提供给程序猿的 API 帮助程序猿简单高效的开发一 个 web app 今天讲一下如何建立一个servlet项目 注意 基于meven创建servlet项目 前提meven要下
  • Clion远程调试树莓派并传递视频流

    Clion远程调试树莓派并传递视频流 0 前言 1 远程调试配置 1 1 远端配置 1 2 本地配置 2 视频流传输 环境 windows10 LTSC raspi 0 前言 近期学习opencv 并准备一些比赛项目 听学长介绍Clion可
  • Linux 网卡重新获取IP

    1 所有网卡驱动重新加载 service network restart 2 对单一网卡进行操作 ifconfig a 获取所有网卡信息 可以看到所有网卡的名字 ifconfig 网卡名称 down ifconfig 网卡名称 up 3 D
  • nvme测试工具:nvme_cli

    nvme cli工具是用于对nvme盘测试的一款通用工具 提供了读写块 查看control namespace信息等功能 下载路径 nvme cli工具是用于对nvme盘进行测试的一款通用工具 其它文档类资源 CSDN下载 如果需要交叉编译
  • 运行node出现“ operation not permitted”错误解决办法

    windows系统下使用node js在使用npm安装express时报错的解决方法 安装时出现如下错误 C Users admin gt npm uninstall express gnpm ERR Windows NT 10 0 143
  • 雷军写的代码上热搜了

    雷军写的代码 一词突然上了微博热搜 一瞬间 我想起了这张图 到底发生了什么 好奇的我点进去一看 原来是因为雷军预告年度演讲的微博里配了一张海报 这张海报信息量非常大 一眼就能看到有很多代码元素 放大一点看看局部 这还是16位实模式下的汇编语
  • JSONObject重复引用导致结果中出现$ref的问题

    转自链接 https blog csdn net baceng article details 92836486 解决办法 先把JSONObject转换成String 然后再转换回JSONObject 例 bussinessData JSO
  • MAYA基础知识和技巧总结

    目录 自定义工具架 自定义热盒 打开Maya时隐藏Output Window 快捷键 小技巧 元素选择技巧 隐藏和显示元素的几种方法 多切割工具 加线 切割 补面的几种方法 复制的几种方法 加入参考图并锁定不动 曲线建模技巧 双轨成型工具
  • CUDA 编程入门

    CUDA 编程入门 更好的阅读体验 CUDA 概述 CUDA 是 NVIDIA 推出的用于其发布的 GPU 的并行计算架构 使用 CUDA 可以利用 GPU 的并行计算引擎更加高效的完成复杂的计算难题 在目前主流使用的冯 诺依曼体系结构的计
  • mongoDB使用总结

    windows安装 zip压缩包方式安装 下载 注意 因为现在最新版的mongodb不兼容win7 对windows系统的最低要求是win10 所以win7系统要安装mongodb数据库必须考虑使用旧版安装 Download MongoDB
  • 一个强大的漏洞公告网站

    http seclists org 通过一篇文章 MySQL 严重 Bug 用户登陆漏洞 得知的这个网站 强大
  • Python不是一门伟大的语言

    作为一门简洁易用 生态蓬勃且具有高泛用性的编程语言 Python一直以来都被不少人称作 编程语言中的瑞士军刀 尤其随着近来AI热潮席卷全球 Python在编程语言圈中的地位也随之水涨船高 甚至一度被视作AI专用语言或大数据专用语言 然而从语
  • 数据结构---归并排序

    归并排序 第一步 分组 第二步 归并 归并操作 第一步 第二步 第三步 JAVA实现 总结 第一步 分组 第1层分成2个大组 每组n 2个元素 第2层分成4个小组 每组n 4个元素 第3层分成8个更小的组 每组n 8个元素 一直到每组只有一
  • 各种经纬度坐标系转换-百度坐标系、火星坐标系、国际坐标系

    各种经纬度坐标系转换 百度坐标系 火星坐标系 国际坐标系 文章代码参考网上 测试没什么问题 汇总整理希望对大家有帮助 dou WGS84 国际坐标系 为一种大地坐标系 也是目前广泛使用的GPS全球卫星定位系统使用的坐标系 GCJ02 火星坐
  • UE4中使用数据表(Data Table)

    本文依据官方文档数据驱动游戏性元素整理而来 做过游戏的应该都清楚 如果游戏稍微有点规模 那么使用数据驱动来做游戏一般是必不可少的一步 一般也就是策划通过本表的方式来解决 下面我们来简单说一下UE4中如何使用DataTable来实现数据驱动开
  • MobileViG实战:使用MobileViG实现图像分类任务(一)

    文章目录 摘要 安装包 安装timm 安装 grad cam 数据增强Cutout和Mixup EMA 项目结构 计算mean和std 生成数据集 摘要 论文翻译 https blog csdn net m0 47867638 articl
  • 获取cookie的两种方式EL表达式中判断数据是否为空

    1 使用java代码获取cookie Cookie cs request getCookies 通过请求获取 for Cookie c cs if c getName equals loginAct String loginAct c ge
  • js总结(二)--彻底理解js中this的指向,不必硬背。

    首先必须要说的是 this的指向在函数定义的时候是确定不了的 只有函数执行的时候才能确定this到底指向谁 实际上this的最终指向的是那个调用它的对象 这句话有些问题 后面会解释为什么会有问题 虽然网上大部分的文章都是这样说的 虽然在很多