阮一峰的JavaScript 的 this 原理

一、问题的由来

学懂 JavaScript 语言,一个标志就是理解下面两种写法,可能有不一样的结果。


var obj = {foo: function () {}
};var foo = obj.foo;// 写法一
obj.foo()// 写法二
foo()

上面代码中,虽然obj.foofoo指向同一个函数,但是执行结果可能不一样。请看下面的例子。


var obj = {foo: function () { console.log(this.bar) },bar: 1
};var foo = obj.foo;
var bar = 2;obj.foo() // 1
foo() // 2

这种差异的原因,就在于函数体内部使用了this关键字。很多教科书会告诉你,this指的是函数运行时所在的环境。对于obj.foo()来说,foo运行在obj环境,所以this指向obj;对于foo()来说,foo运行在全局环境,所以this指向全局环境。所以,两者的运行结果不一样。

这种解释没错,但是教科书往往不告诉你,为什么会这样?也就是说,函数的运行环境到底是怎么决定的?举例来说,为什么obj.foo()就是在obj环境执行,而一旦var foo = obj.foofoo()就变成在全局环境执行?

本文就来解释 JavaScript 这样处理的原理。理解了这一点,你就会彻底理解this的作用。

二、内存的数据结构

JavaScript 语言之所以有this的设计,跟内存里面的数据结构有关系。


var obj = { foo:  5 };

上面的代码将一个对象赋值给变量obj。JavaScript 引擎会先在内存里面,生成一个对象{ foo: 5 },然后把这个对象的内存地址赋值给变量obj

也就是说,变量obj是一个地址(reference)。后面如果要读取obj.foo,引擎先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的foo属性。

原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。举例来说,上面例子的foo属性,实际上是以下面的形式保存的。


{foo: {[[value]]: 5[[writable]]: true[[enumerable]]: true[[configurable]]: true}
}

注意,foo属性的值保存在属性描述对象的value属性里面。

三、函数

这样的结构是很清晰的,问题在于属性的值可能是一个函数。


var obj = { foo: function () {} };

这时,引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。


{foo: {[[value]]: 函数的地址...}
}

由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行。


var f = function () {};
var obj = { f: f };// 单独执行
f()// obj 环境执行
obj.f()

四、环境变量

JavaScript 允许在函数体内部,引用当前环境的其他变量。


var f = function () {console.log(x);
};

上面代码中,函数体里面使用了变量x。该变量由运行环境提供。

现在问题就来了,由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。


var f = function () {console.log(this.x);
}

上面代码中,函数体里面的this.x就是指当前运行环境的x


var f = function () {console.log(this.x);
}var x = 1;
var obj = {f: f,x: 2,
};// 单独执行
f() // 1// obj 环境执行
obj.f() // 2

上面代码中,函数f在全局环境执行,this.x指向全局环境的x

obj环境执行,this.x指向obj.x

回到本文开头提出的问题,obj.foo()是通过obj找到foo,所以就是在obj环境执行。一旦var foo = obj.foo,变量foo就直接指向函数本身,所以foo()就变成在全局环境执行。

 

 

总结:

this是用于在函数体内部,指代函数当前的运行环境。
 

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

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

相关文章

计算机基础:IP地址,子网掩码,默认网关,DNS服务器

如图各项IP地址、子网掩码、默认网关、DNS服务器分别都代表什么意思 (一)IP地址 IP是32位二进制数据,通常以十进制表示,并以“.”分隔。IP地址是一种逻辑地地址,用来标识网络中一个个主机,IP有唯一性&#…

解决vue的{__ob__: observer}取值问题

vue编码中经常出现获取到的数据是:{__ob__: Observer} 格式的,详细如下 可能导致后续数据操作错误,如何获取其中的数值呢 解决方法如下: 将返回的数据data先转换为JSON字符串形式,然后再从字符串形式转换成JSON格式JS…

软考计算机基础:存储系统

软考计算机存储系统笔记: 存储器分类: 1、按存储位置分为内存和外存; 2、按存储材料分为磁存储(使用磁存储介质)、半导体存储(分为双极型和MOS型,根据数据是否需要刷新可以分为静态SRAM存储器…

vscode统计代码行数,前端开发配置、快捷键使用

1、统计代码行数 使用场景是项目年终统计行数。 实现:在需要统计得文件夹右键“在文件夹中查找“ ,后输入筛选得正则表达式 ^b*[^:b#/].*$ (注意右边小图标都点亮) 这里顺便将自己使用vscode进行前端开发环境配置归纳一下,便于自己以后快速…

vue-cli打包后怎么修改服务器地址实践有效

前言:公司vue项目使用 npm run build 打包生成dist文件部署后,当需要修改服务器端地址时候就又需要重新配置url并打包部署,为简化部署测试工作,想实现通过修改服务器地址的配置文件来实现修改打包后的项目服务器地址。 项目基于vu…

干净高效的搜索引擎

找一个干净好用的搜索引擎,好文转载备忘 为什么不用百度搜索引擎,估计一百个人会有一百个理由。 百度最让人诟病的还是它的竞价排名,其实要赚钱无可厚非,但这吃相……前几天看到知乎上有人发了张百度和谷歌搜索的对比图&#xf…

vue-router区分hash模式和history模式

总结: hash模式是我们在url后面添加一个#xx触发事件。尽管浏览器没有请求服务器,但是页面状态和url已经关联起来了,这就是所谓的前端路由,单页应用的标配。 history模式下浏览器地址不规整(没有#)&#x…

Vue 打包前需修改的配置,解决白屏问题

vue-cli项目和electron-vue项目打包运行都有遇到的白屏问题,下面记录打包前需要确认的配置 第一: config文件夹下的index.js 中的文件中的 assetsPublicPath :‘/’ 改为’./’ 不然的话会是空白页,记住,是build那块。…

electron-vue解决打包错误、无法调用出开发者工具(亲测有效)

错误1: unresolved node modules vue... 或 not found modules..的错误 解决方式:依赖的模块错误,删除node_module文件夹后,尽量用npm install而不是淘宝镜像cnpm安装 错误2: Cannot create symlinks (on Windows hos…

JS中使用bignumber处理高精度小数运算

项目开发中发现精度丢失的问题,如0.10.2 0.30000000000000004的问题 解决方式:引用bignumber.js用于数字精度要求较高的计算。 1、安装或引用: 下载地址:https://github.com/MikeMcl/bignumber.js/releases 或 npm install big…

restful api接口设计

技术由来: 互联网早期,页面请求和并发量不高,且移动端未盛行时对接口要求不高,使用动态页面(jsp)就能满足绝大多数的使用需求。但是随着互联网和移动设备的发展,人们对Web应用的使用需求也增加,传统的动态…

vue-cli安装和使用

主要记录安装vue-cli制定版本和使用,注意vue-cli4创建项目命令和项目结构的改变 检查当前项目的vue-cli版本: vue -V 卸载当前版本: npm uninstall vue-cli -g 安装最新版本: npm install -g vue-cli 安装指定版本: npm in…

Apache 和 Tomcat 服务器的区别

Apache 和 Tomcat 都是web网络服务器,两者既有联系又有区别,在进行HTML、PHP、JSP、Perl等开发过程中,需要准确掌握其各自特点,选择最佳的服务器配置。 Apache是web服务器(静态解析,如HTML)&…

二进制、八进制、十六进制相互转换

一、十进制与二进制之间的转换 1、十进制转二进制 方法为:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。 (具体用法如下图) 2、二…

vue-cli3+与vue-cli2的区别和vue-cli 修改配置

vue-cli3是基于webpack4打造,vue-cli2是基于webpack3vue-cli3的设计原则是“0配置”,移除(隐藏)配置文件build和config等目录vue-cli3提供了vue ui 命令,提供了可视化配置vue-cli3移除了static文件夹,新增了…

electron打包vue-cli4项目的解决方案1(项目实测)

背景: 项目已通过vue-cli4框架开发并运行在nginx服务器上(使用了nginx的反向代理),现需要将该项目转成桌面端应用程序,选择electron来实现。 设想2种解决方案: 1、使用electron-quick-start的loadURL方法…

IP 基础知识“全家桶”,45 张图一套带走!

转载自: https://mp.weixin.qq.com/s/kPjFeefB1Xsbc2bHz_Or1Q 前言 前段时间,有读者希望我写一篇关于 IP 分类地址、子网划分等的文章,他反馈常常混淆,摸不着头脑。 那么,说来就来!而且要盘就盘全一点&am…

浅谈XSS攻击的那些事(附常用绕过姿势)

本文《浅谈XSS攻击的那些事(附常用绕过姿势)》 由一叶知安团队原创投稿安全脉搏首发,作者geek痕,安全脉搏独家首发表本文,如需要转载,请先联系安全脉搏授权;未经授权请勿转载。随着互联网的不断发展&#x…

了解与防御XSS攻击

一. XSS是什么 XSS攻击全称跨站脚本攻击(Cross Site Scripting),是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意…

BS架构和CS架构的优缺点

1、CS、BS架构定义 CS(Client/Server):客户端----服务器结构。C/S结构在技术上很成熟,它的主要特点是交互性强、具有安全的存取模式、网络通信量低、响应速度快、利于处理大量数据。因为客户端要负责绝大多数的业务逻辑和UI展示&a…