javascript中this指向详解
理解 JavaScript 中 `this` 的指向是深入理解这门语言的关键一环。在函数定义的时候,`this` 的指向是确定不了的,只有在函数被执行的时候,`this` 的指向才会明晰,指向调用它的对象。实际上,`this` 最终指向的是那个调用它的对象。接下来,我们将深入这个问题。
JavaScript 是一种支持函数式编程、闭包和基于原型的继承等高级功能的脚本语言。随着对 JavaScript 的深入使用,你会发现其基本概念中 `this` 关键字的使用是一大难点。在不同的场景下,`this` 会指向不同的对象。要真正掌握 JavaScript,就需要理解 `this` 的工作机制。
在主流的面向对象的语言中(如 Java、C 等),`this` 的含义是明确且具体的,即指向当前对象,一般在编译期绑定。而 JavaScript 中的 `this` 是在运行期绑定的,这是 JavaScript 中 `this` 关键字具备多重含义的本质原因。
由于 JavaScript 的运行期绑定特性,`this` 可以是全局对象、当前对象或者任意对象,完全取决于函数的调用方式。JavaScript 中函数的调用有以下几种方式:作为对象方法调用、作为函数调用、作为构造函数调用以及使用 `apply` 或 `call` 调用。
为了更好地理解 JavaScript 中 `this` 的指向,我们可以通过一个决策树来进行解释。以你提供的例子来说:
```javascript
var point = {
x: 0,
y: 0,
moveTo: function(x, y) {
this.x = this.x + x;
this.y = this.y + y;
}
};
```
当执行 `point.moveTo(1,1)` 时,`this` 绑定到当前对象 `point`。这里的决策过程是:函数不是用 `new` 进行调用的,而是用 dot(.)进行调用的,所以 `this` 指向 `moveTo` 方法之前的对象 `point`。
再来看另一个例子:
```javascript
function func(x) {
this.x = x;
}
func(5); // this 是全局对象 window,x 为全局变量
```
在这个例子中,`func(5)` 函数调用不是用 `new` 进行调用的,也不是用 dot(.)进行调用的,所以 `this` 指向全局对象 `window`。`this.x` 实际上就是 `window.x`。
对于函数内部定义的函数(如 `moveX` 和 `moveY`),它们的 `this` 指向是由它们所在的环境决定的。如果它们被直接调用(不是作为对象的方法),那么 `this` 通常指向全局对象(在浏览器中是 `window`)。
JavaScript中的`this`决策树
在JavaScript中,`this`是一个特殊的关键字,它的值取决于函数的调用方式。为了更好地理解这一过程,我们可以将其比喻为一棵“决策树”。
让我们从`Point`类的一个例子开始。假设我们有一个`moveTo`方法,它接受两个参数并更新点的坐标。
```javascript
function Point(x, y) {
this.x = x;
this.y = y;
this.moveTo = function(x, y) {
this.x = x;
this.y = y;
}
}
```
当我们调用`point.moveTo(1,1)`时,实际上是在内部调用了`moveX()`和`moveY()`函数。这里的`this`是如何被决定的呢?我们可以按照“JavaScript `this`决策树”来理解:
1. 如果函数是通过`new`关键字调用的,那么`this`指向新创建的对象。例如,`var np = new Point(1,1)`中,`this`指向`np`,所以`np.x = 1`。
2. 如果函数是通过点标记法(`.`)调用的,那么`this`指向该点标记的对象。但在我们的例子中,直接调用`Point(2,2)`而不是通过点标记法,所以`this`指向全局对象`window`,因此`window.x = 2`。
接下来,让我们看一个使用`call`和`apply`方法的例子。这两个方法允许我们切换函数执行的上下文环境,即改变`this`绑定的对象。
```javascript
var p1 = new Point(0, 0);
var p2 = {x: 0, y: 0};
p1.moveTo.apply(p2, [10, 10]); // 这实际上是p2.moveTo(10,10)的调用方式。
```
在这里,当我们调用`p1.moveTo.apply(p2,[10,10])`时,我们可以按照“JavaScript `this`决策树”进行判定:该函数调用并不是通过`new`关键字或点标记法进行的,而是通过apply方法切换了上下文。这里的`this`指向了`apply`的第一个参数,即对象`p2`。经过这次调用后,`p2.x = 10`。
为了更好地理解这一切,我们可以引用IBM developerworks文档库中的描述:JavaScript中的函数既可以作为普通函数执行,也可以作为对象的方法执行,这导致了`this`含义的丰富性。一个函数被执行时,会创建一个执行环境,所有的行为均发生在此环境中。在这个环境中,JavaScript会创建包含调用函数时传入的参数的`arguments`变量,并构建作用域链。
我们要初始化一系列变量,这些变量来自于函数的形参列表,它们的值来源于arguments变量。如果在arguments变量中没有找到对应的值,那么这些形参将被初始化为undefined。这些形参构成了函数执行的基础环境——ExecutionContext(执行上下文)。
接下来,如果这个函数内部还包含其他的函数,我们也需要对这些内部函数进行初始化。如果函数中没有内部函数,那么我们继续初始化函数内部定义的局部变量。值得注意的是,这些局部变量的初始值都是undefined,它们的实际赋值操作会在函数执行时完成。这个过程对于我们理解JavaScript中的变量作用域至关重要。尽管这个话题深入且复杂,但在这里我们暂时先搁置讨论。
还有一个重要的步骤是给this变量赋值。这个赋值的过程会根据函数调用的方式而有所不同,它可能会被赋值为全局对象或者当前对象等。至此,函数的执行环境(ExecutionContext)已经构建完成。然后,函数开始逐行执行,所有需要的变量都可以从已经构建好的执行环境中获取。
在理解了上述过程后,我们将更好地掌握JavaScript函数的运作机制。现在让我们看看接下来会发生什么吧:Cambrian代码开始渲染主体部分了。让我们期待它会带来怎样的视觉盛宴。 cambrian.render('body')
网络安全培训
- javascript中this指向详解
- JavaScript中this的9种应用场景及三种复合应用场景
- php 使用curl模拟ip和来源进行访问的实现方法
- jQuery插件实现可输入和自动匹配的下拉框
- jQuery子属性过滤选择器用法分析
- 漂亮! js实现颜色渐变效果
- 使用puppeteer破解极验的滑动验证码
- jQuery插件FusionCharts绘制ScrollColumn2D图效果示例【附
- asp.net DoDragDrop 方法的使用
- Vue.js bootstrap前端实现分页和排序
- PHP+jquery+ajax实现分页
- lhgcalendar时间插件限制只能选择三个月的实现方法
- 微信小程序之仿微信漂流瓶实例
- Bootstrap 表单验证formValidation 实现表单动态验证功
- 基于vue2框架的机器人自动回复mini-project实例代码
- 关于Vue单页面骨架屏实践记录