JavaScript 中this的实现原理
学懂 JavaScript 言语,一个标志就是了解下面两种写法,或许有不一样的成果。
<blockquote "="">
var obj = { foo: function () {} }; var foo = obj.foo; // 写法一 obj.foo() // 写法二 foo()
上面代码中,尽管obj.foo和foo指向同一个函数,可是履行成果或许不一样。请看下面的比如。
<blockquote "="">
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.foo,foo()就变成在大局环境履行?
本文就来解释 JavaScript 这样处理的原理。了解了这一点,你就会完全了解this的效果。
二、内存的数据结构
JavaScript 言语之所以有this的规划,跟内存里边的数据结构有关系。
<blockquote "="">
var obj = { foo: 5 };
上面的代码将一个目标赋值给变量obj。JavaScript 引擎会先在内存里边,生成一个目标{ foo: 5 },然后把这个目标的内存地址赋值给变量obj。

也就是说,变量obj是一个地址(reference)。后面如果要读取obj.foo,引擎先从obj拿到内存地址,然后再从该地址读出原始的目标,返回它的foo特点。
原始的目标以字典结构保存,每一个特点名都对应一个特点描绘目标。举例来说,上面比如的foo特点,实际上是以下面的方式保存的。

<blockquote "="">
{ foo: { [[value]]: 5 [[writable]]: true [[enumerable]]: true [[configurable]]: true } }
留意,foo特点的值保存在特点描绘目标的value特点里边。
三、函数
这样的结构是很明晰的,问题在于特点的值或许是一个函数。
<blockquote "="">
var obj = { foo: function () {} };
这时,引擎会将函数独自保存在内存中,然后再将函数的地址赋值给foo特点的value特点。

<blockquote "="">
{ foo: { [[value]]: 函数的地址 ... } }
因为函数是一个独自的值,所以它可以在不同的环境(上下文)履行。
<blockquote "="">
var f = function () {}; var obj = { f: f }; // 独自履行 f() // obj 环境履行 obj.f()
四、环境变量
JavaScript 允许在函数体内部,引用当时环境的其他变量。
<blockquote "="">
var f = function () { console.log(x); };
上面代码中,函数体里边使用了变量x。该变量由运转环境提供。
现在问题就来了,因为函数可以在不同的运转环境履行,所以需要有一种机制,http://www.qijihu.com专卖网站可以在函数体内部获得当时的运转环境(context)。所以,this就呈现了,它的规划意图就是在函数体内部,指代函数当时的运转环境。
<blockquote "="">
var f = function () { console.log(this.x); }
上面代码中,函数体里边的this.x就是指当时运转环境的x。
<blockquote "="">
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()就变成在大局环境履行。
(完)
JavaScript 中this的实现原理的更多相关文章
- JavaScript中实现DI的原理(二)
JavaScript中实现DI的原理 在JavaScript中实现DI,看起来难,实际上原理很简单,它的核心技术是Function对象的toString().我们都知道,对一个函数对象执行toStri ...
- JavaScript中this的工作原理以及注意事项
在JavaScript中,this 的概念比较复杂.除了在面向对象编程中,this 还是随处可用的.这篇文章介绍了this 的工作原理,它会造成什么样的问题以及this 的相关例子. 要根据this ...
- 详解javascript中this的工作原理
在 JavaScript 中 this 常常指向方法调用的对象,但有些时候并不是这样的,本文将详细解读在不同的情况下 this 的指向. 一.指向 window: 在全局中使用 this,它将会指向全 ...
- 【干货理解】理解javascript中实现MVC的原理
理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...
- javaScript中闭包的工作原理
一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...
- javascript中new操作符的原理
javascript中的new是一个语法糖,对于学过c++,java 和c#等面向对象语言的人来说,以为js里面是有类和对象的区别的,实现上js并没有类,一切皆对象,比java还来的彻底 new的过程 ...
- JavaScript中的作用域链原理
执行环境 作用域链的形成与执行环境(Execution Environment)相关,在JavaScript当中,产生执行环境有如下3中情形: 1 进入全局环境 2 调用eval函数 3 调用func ...
- JavaScript中的原型继承原理
在JavaScript当中,对象A如果要继承对象B的属性和方法,那么只要将对象B放到对象A的原型链上即可.而某个对象的原型链,就是由该对象开始,通过__proto__属性连接起来的一串对象.__pro ...
- JavaScript中的原型链原理
工作中经常解除到prototype的概念,一开始错误的认为prototype是对象的原型链,其实prototype只能算是JavaScript开放出来的原型链接口,真正的原型链概念应该是__proto ...
随机推荐
- spark快速大数据分析
从上层来看,每个Spark 应用都由一个驱动器程序(driver program)来发起集群上的各种并行操作.驱动器程序包含应用的main 函数,并且定义了集群上的分布式数据集,还对这些分布式数据集应 ...
- 使用Shiro登录成功后,跳转到之前访问的页面实现
转:http://blog.csdn.net/lhacker/article/details/20450855 很多时候,我们需要做到,当用户登录成功后,跳转回登录前的页面.如果用户是点击" ...
- Python基础1 介绍、基本语法
---恢复内容开始--- 本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表 ...
- Centos下lnmp正确iptables配置规则
查看iptable运行状态 service iptables status 清除已有规则 iptables -Fiptables -Xiptables -Z 开放端口 #允许本地回环接口(即运行本机访 ...
- Tomcat命令
如果原始内存不够用经常内存溢出,可以在catalina.bat中设置: 电脑2G内存的情况 :set JAVA_OPTS='-server -Xms1024m -Xmx1536m -XX:PermSi ...
- UI5-学习篇-9-本地Eclipse UI5应用发布到SAP前端服务器
参考路径: https://blogs.sap.com/2017/11/19/sap-fiori-ui5-application-deployment/ 1.准备环境 2.上载SAP-FIORI前端服 ...
- Django下的templates 和 static静态文件
如果Django顶层目录中没有templates的话,就自己新建一个Directory ,这个文件是存放html文件的 1)如果在views里面用render(request,"" ...
- JAVA_连接池、DataSource、JNDI
1.连接池 Connection的取得和开放是代价比较高的处理,解决这个问题的方法是连接池. 连接池就是事先取得一定数量的Connection,程序执行处理的时候不是新建Connectio ...
- 尚硅谷springboot学习19-日志切换
查看相关依赖关系,排除相关依赖,引入新的日志依赖 slf4j+log4j的方式: <dependency> <groupId>org.springframework.boot& ...
- Android进阶AIDL - 2018年4月14日
参考:慕课网 --- 最后三集.Android开发艺术探索 1.在AS中创建aidl文件后,要编译一下才会在gen下生成debug文件: 2.AIDL 不支持short类型,常用的数据类型: 3.AI ...