this一直困扰我很久,在网上摘了一篇与大家一起学习,如有不妥之处还望谅解!
1.2 this 和执行上下文
在前面讨论封装时,我们已经接触过 this 了。在对封装的讨论中,我们看到的 this 都是表示 this 所在的类的实例化对象本身。真的是这样吗?
先看一下下面的例子吧:
-
varx="I'm
a global variable!";
-
functionmethod(){
-
alert(x);
-
alert(this.x);
-
}
-
functionclass1(){
-
//
private field
-
varx="I'm
a private variable!";
-
//
private method
-
functionmethod1(){
-
alert(x);
-
alert(this.x);
-
}
-
varmethod2=method;
-
//
public field
-
this.x="I'm
a object variable!";
-
//
public method
-
this.method1=function(){
-
alert(x);
-
alert(this.x);
-
}
-
this.method2=method;
-
//
constructor
-
{
-
this.method1();
// I'm a private variable!
-
//
I'm a object variable!
-
this.method2();
// I'm a global variable!
-
//
I'm a object variable!
-
method1();
// I'm a private variable!
-
//
I'm a global variable!
-
method2();
// I'm a global variable!
-
//
I'm a global variable!
-
method1.call(this);//
I'm a private variable!
-
//
I'm a object variable!
-
method2.call(this);//
I'm a global variable!
-
//
I'm a object variable!
-
}
-
}
-
-
varo=newclass1();
-
method();
// I'm a global variable!
-
//
I'm a global variable!
-
o.method1();
// I'm a private variable!
-
//
I'm a object variable!
-
o.method2();
// I'm a global variable!
-
//
I'm a object variable!
为什么是这样的结果呢?
那就先来看看什么是执行上下文吧。那什么是执行上下文呢?
如果当前正在执行的是一个方法,则执行上下文就是该方法所附属的对象,如果当前正在执行的是一个创建对象(就是通过 new 来创建)的过程,则创建的对象就是执行上下文。
如果一个方法在执行时没有明确的附属于一个对象,则它的执行上下文是全局对象(顶级对象),但它不一定附属于全局对象。全局对象由当前环境来决定。在浏览器环境下,全局对象就是
window 对象。
定义在所有函数之外的全局变量和全局函数附属于全局对象,定义在函数内的局部变量和局部函数不附属于任何对象。
那执行上下文跟变量作用域有没有关系呢?
执行上下文与变量作用域是不同的。
一个函数赋值给另一个变量时,这个函数的内部所使用的变量的作用域不会改变,但它的执行上下文会变为这个变量所附属的对象(如果这个变量有附属对象的话)。
Function 原型上的 call 和 apply 方法可以改变执行上下文,但是同样不会改变变量作用域。
要理解上面这些话,其实只需要记住一点:
变量作用域是在定义时就确定的,它永远不会变;而执行上下文是在执行时才确定的,它随时可以变。
这样我们就不难理解上面那个例子了。this.method1() 这条语句(注意,这里说的还没有进入这个函数体)执行时,正在创建对象,那当前的执行上下文就是这个正在创建的对象,所以 this 指向的也是当前正在创建的对象,在 this.method1() 这个方法执行时(这里是指进入函数体),这个正在执行的方法所附属的对象也是这个正在创建的对象,所以,它里面 this.x 的 this 也是同一个对象,所以你看的输出就是 I’m a object variable! 了。
而在执行 method1() 这个函数时(是指进入函数体后),method1() 没有明确的附属于一个对象,虽然它是定义在 class1 中的,但是他并没有不是附属于 class1 的,也不是附属于 class1 实例化后的对象的,只是它的作用域被限制在了 class1 当中。因此,它的附属对象实际上是全局对象,因此,当在它当中执行到 alert(this.x) 时,this.x 就成了我们在全局环境下定义的那个值为 “I’m a global variable!” 的 x 了。
method2() 虽然是在 class1 中定义的,但是 method() 是在 class1 之外定义的,method 被赋值给 method2 时,并没有改变 method 的作用域,所以,在 method2 执行时,仍然是在 method 被定义的作用域内执行的,因此,你看到的就是两个 I’m a global variable! 输出了。同样,this.method2() 调用时,alert(x) 输出 I’m a global variable! 也是这个原因。
因为 call 会改变执行上下文,所以通过 method1.call(this) 和 method2.call(this) 时,this.x 都变成了 I’m a object variable!。但是它不能改变作用域,所以 x 仍然跟不使用 call 方法调用时的结果是一样的。
而我们后面执行 o.method1() 时,alert(x) 没有用 this 指出 x 的执行上下文,则 x 表示当前执行的函数所在的作用域中最近定义的变量,因此,这时输出的就是 I’m a private variable!。最后输出 I’m a object variable! 我想不用我说大家也知道为什么了吧?:D
分享到:
相关推荐
(一)创建阶段 (二)执行阶段 一、执行上下文是什么 代码运行是在一定的环境之中运行的,这个运行环境我们就成为执行环境,也就是执行上下文,按照执行环境不同,我们可以分为三类: 全局执行环境:代码首次...
所以 JavaScript 引擎创建了执行上下文栈(Execution context stack,ECS)来管理执行上下文为了模拟执行上下文栈的行为,让我们定
详细讲解javascript中执行上下文、函数堆栈、变量提升的原理,对代码解析运行过程有更深层的理解
作为一个前端开发人员,弄清楚JavaScript的执行上下文有助于我们理解js中一些晦涩的概念,比如闭包,作用域,变量提升等等。 执行栈 执行栈用于存储代码执行期间创建的所有执行上下文。具有FILO接口,也被称为调用...
执行上下文就是当前的 JavaScript 代码被解析和执行时所在环境的抽象概念, JavaScript 中运行任何的代码都是在执行上下文中运行的. 2 执行上下文的类型 执行上下文分为三种类型: 全局执行上下文:只有一个,这是默认...
主要介绍了JavaScript 中的执行上下文和执行栈的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
js上下文理解js上下文理解js上下文理解js上下文理解js上下文理解js上下文理解js上下文理解js上下文理解js上下文理解js上下文理解
面向对象概念(对象封装,各种继承,闭包原理,this作用域等)介绍清晰易懂
本文实例讲述了javascript执行上下文、变量对象。分享给大家供大家参考,具体如下: 突然看到一篇远在2010年的老文,作者以章节的形式向我们介绍了ECMA-262-3的部分内容,主要涉及到执行上下文、变量对象、作用域、...
在这篇文章里,我将深入研究JavaScript中最基本的部分——执行上下文(execution context)。读完本文后,你应该清楚了解释器做了什么,为什么函数和变量能在声明前使用以及他们的值是如何决定的。 1、EC—执行环境...
什么是执行上下文? JavaScript的执行环境非常重要,当JavaScript代码在行时,会被预处理为以下情况之一: ...这里没有什么特别之处,我们有一个由紫色边框表示的全局上下文,和由绿色,蓝色和橙色边框
文章目录变量提升执行上下文全局执行上下文函数执行上下文执行上下文栈作用域例题举个栗子 执行上下文栈:举个栗子 变量提升+执行上下文栈:举个栗子 预处理顺序举个栗子 预处理举个栗子 顺序执行举个栗子 作用域举...
1.当代码执行的时候,首先生成一个全局执行上下文(global EC) 2.当执行到函数作用域时,全局执行上下文(caller)会触发该函数执行上下文(call
1.通过函数的call法设置 1.通过函数的call法设置 2.通过对象调法设置 2.通过对象调法设置 3.通过构造函数中设置 3.通过构造函数中设
Javascript中this关键字通常指向当前函数的拥有者。在javascript中通常把这个拥有者叫做执行上下文。
JavaScript 采用词法作用域(lexical scoping),函数执行依赖的变量作用域是由函数定义的时候决定,而不是函数执行的时候决定,通过本文给大家介绍JavaScript作用域链、执行上下文与闭包相关知识,感兴趣的朋友一起...
javascript编译以及执行过程详细讲解,包括预编译和执行