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 ...
随机推荐
- TCP/UDP模型
1网络接口层 MAC地址2网络互联层 IP地址3传输层 TCP/UDP端口号4应用层 应用层协议
- Timer TimerTask schedule scheduleAtFixedRate
jdk 自带的 timer 框架是有缺陷的, 其功能简单,而且有时候它的api 不好理解. import java.util.Date; import java.util.Timer; import ...
- node-disconf-client基本配置
node-disconf-client 需要cppm install node-disconf-client var disconf = require (' node-disconf-clien ...
- twisted之Deferred类的分析
@_oldStyle class Deferred: called = False#类变量,在实例中引用时会自动在实例中生成 paused = False _debugInfo = None _sup ...
- 使用STM32CubeMX生成USB_HOST_HID工程[添加对CAPS_LOCK指示灯的控制][SetReport]
在之前(使用STM32CubeMX生成USB_HOST_HID工程)的基础上进行修改 在结合之前在pc上的测试 USB之HID类Set_Report Request[调试手记1] 测试代码如下: /* ...
- nginx 和 php超时设置
nginx.conf --- http节: keepalive_timeout 600; #客户端浏览器超时时间fastcgi_connect_timeout 600; #php-fpm连接超时时间 ...
- Redis简单生产者消费者
注意:redis客户端执行是单线程的,不能将客户端放在外面,内部执行使用多线程的方式. // 创建生产端连接 final Jedis jedisProducter = new Jedis(R_HOST ...
- Oracle部署安装
1.用户有数据库服务器则不需要安装Oracle服务器端,若没有需要安装 https://jingyan.baidu.com/article/363872eccfb9266e4aa16f5d.html ...
- spring集成mybatis的mybatis参考配置
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration PUBLIC &q ...
- RTS寻路相关资料收集
http://www.cocoachina.com/game/20150824/13174.html RVO算法 RVO避开agent