java that_JAVA中关于this和that的一些知识

新手在入门 Java 的过程中,一定会踩很多关于 this 的坑,出现问题的本质就是 this 指针的指向和自己想的不一样。笔者在入门学习的过程中,也踩了很多坑,于是便写下本篇文章记录自己“踩坑”历程。

一。 this 在哪里?

在上篇《从 Java 作用域说开去》分析中,我们知道,在 ExecuTIon Context 中有一个属性是 this,这里的 this 就是我们所说的 this 。this 与上下文中可执行代码的类型有直接关系,this 的值在进入执行上下文时确定,并且在执行上下文运行期间永久不变。

this 到底取何值?this 的取值是动态的,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了。因为 this 的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境。

所以 this 的作用就是用来指明执行上下文是在哪个上下文中被触发的对象。令人迷惑的地方就在这里,同一个函数,当在不同的上下文进行调用的时候,this 的值就可能会不同。也就是说,this 的值就是函数调用表达式(也就是函数被调用的方式)的 caller。

二。 this & that 具体指的是谁?

目前接触的有以下14种情况,笔者打算一一列举出来,以后如果遇到了更多的情况,还会继续增加。

既然 this 是执行上下文确定的,那么从执行上下文的种类进行分类,可以分为3种:

那么接下来我们就从 Global ExecuTIon Context 全局执行上下文,FuncTIon ExecuTIon Context 函数执行上下文,Eval Execution Context Eval执行上下文 这三类,具体谈谈 this 究竟指的是谁。

(一)。 全局执行上下文1. 非严格模式下的函数调用

这是函数的最通常用法,属于全局性调用,因此 this 就代表全局对象 Global。

var name = ‘halfrost’;function test() { console.log(this); // window console.log(this.name); // halfrost}test();

在全局上下文(Global Context)中,this 总是 global object,在浏览器中就是 window 对象。

2. 严格模式下的函数调用

严格模式由 ECMA 5.1引进,用来限制 Java 的一些异常处理,提供更好的安全性和更强壮的错误检查机制。使用严格模式,只需要将 ‘use strict’ 置于函数体的顶部。这样就可以将上下文环境中的 this 转为 undefined。这样执行上下文环境不再是全局对象,与非严格模式刚好相反。

在严格模式下,情况并不是仅仅是 undefined 这么简单,有可能严格模式夹杂着非严格模式。

先看严格模式的情况:

‘use strict’;function test() { console.log(this); //undefined};test();

上面的这个情况比较好理解,还有一种情况也是严格模式下的:

function execute() { ‘use strict’; // 开启严格模式 function test() { // 内部函数也是严格模式 console.log(this); // undefined } // 在严格模式下调用 test() // this 在 test() 下是 undefined test(); // undefined } execute();

如果严格模式在外层,那么在执行作用域内部声明的函数,它会继承严格模式。

接下来就看看严格模式和非严格模式混合的情况。

function nonStrict() { // 非严格模式 console.log(this); // window } function strict() { ‘use strict’; // 严格模式 console.log(this); // undefined }

这种情况就比较简单了,各个模式下分别判断就可以了。

(二)。函数执行上下文3. 函数调用

当通过正常的方式调用一个函数的时候,this 的值就会被设置为 global object(浏览器中的 window 对象)。

严格模式和非严格模式的情况和上述全局执行上下文的情况一致,严格模式对应的 undefined ,非严格模式对应的 window 这里就不再赘述了。

4. 方法作为对象的属性被调用

var person = { name: “halfrost”, func: function () { console.log(this + “:” + this.name); }};person.func(); // halfrost

在这个例子里面的 this 调用的是函数的调用者 person,所以会输出 person.name 。

当然如果函数的调用者是一个全局对象的话,那么这里的 this 指向又会发生变化。

var name = “YDZ”;var person = { name: “halfrost”, func: function () { console.log(this + “:” + this.name); }};temp = person.func;temp(); // YDZ

在上面这个例子里面,由于函数被赋值到了另一个变量中,并没有作为 person 的一个属性被调用,那么 this 的值就是 window。

上述现象其实可以描述为,“从一个类中提取方式时丢失了 this 对象”。针对这个现象可以再举一个例子:

var counter = { count: 0, inc: function() { this.count ++; }}var func = counter.inc;func();counter.count; // 输出0,会发现func函数根本不起作用

这里我们虽然把 counter.inc 函数提取出来了,但是函数里面的 this 变成了全局对象了,所以 func() 函数执行的结果是 window.count++。然而 window.count 根本不存在,且值是 undefined,对 undefined 操作,得到的结果只能是 NaN。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值