this是javascript中非常基础的一个知识点,也是一个令很多初学者迷惑的知识点。
Ecmascript中对其描述如下:
There is a this value associated with every active execution context. The this value depends on the caller and the type of code being executed and is determined when control enters the execution context. The this value associated with an execution context is immutable.
this的取值跟executable code的类型直接相关,execute code有三种Global code,Function code 和Eval code。跟this取值有关的是前两种。
this在global code中的取值
这种情况下问题比较简单,this
的值就是global对象本身
this in global code
1 2 3 4 5 6 7 8 9 10 11 12 |
|
demo中的b没有通过var 声明,它实际上不是一个variable,而是window(global)的一个property。变量和属性的一个显著区别就是变量具有{ DontDelete },而后者没有。因此经常说的
不用var能直接声明全局变量
的说法是错误的,事实上它是为windows添加了一个属性。
variable and property
1 2 3 4 |
|
this在function code中的取值
在function code中this
的值不像在global code中那么简单:
- this的值不是与对应的函数绑定的,也就是说不是在函数创建时决定。
- this的值在进入上下文时决定,并且在执行过程中不可变。ie.不能像变量赋值一样为this赋值。
this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
那么是哪些因素影响this的取值呢?在有些文章和书中有这样的说法:
this的取值由函数的定义方式决定,如果函数被定义成全局函数,则对应的this是global;如果函数是一个对象的方法(method),则this的值是对应的对象。
这种说法是错误的。来看一个例子:
Is the definition of function determing this
1 2 3 4 5 6 7 8 9 10 |
|
baz虽然和foo.bar的值一样,也就是指向同一个函数。但是调用结果不一样,因此this的取值不是由函数的定义决定的。
事实上,
this
的值由调用者提供(例如调用函数的父上下文),由函数的调用方式决定。
为什么this
的取值由函数的调用方式决定?
要回答这个问题需要先看下ECMA中的一个内部类型(internal type) – Reference
type
Reference type
Refference
是一个内部类型,没有任何函数能返回Reference
类型的值,无论是built-in函数还是用户定义的函数。
规范中关于Reference
的描述如下:
The internal Reference type is not a language data type. It is defined by this specification purely for expository purposes. However, a value of type Reference is used only as an intermediate result of expression evaluation and cannot be stored as the value of a variable or property.
The Reference type is used to explain the behaviour of such operators as delete, typeof, and the assignment operators.
other use of the Reference type is to explain the determination of the this value for a function call.
A Reference is a reference to a property of an object. A Reference consists of two components, the base object and the property name.
The following abstract operations are used in this specification to access the components of references:
- GetBase(V). Returns the base object component of the reference V.
- GetPropertyName(V). Returns the property name component of the reference V.
Reference
的结构可以描述如下:
Reference的结构
1 2 3 4 |
|
根据规范,仅在以下两种情况时会返回Reference
类型的值:
- 标识符解析(identifiers resolution),标识符包括变量名,函数名,函数参数名,还有就是上面提到的不用var声明,直接赋值的变量。
- 属性访问(Property access),属性访问有两种方式,通过
[]
或者.
,如foo.bar
,foo['bar']
Reference
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Reference
是一个中间值,要获取real value,需要用到GetValue
方法(参见),其伪代码如下:
GetValue 伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
[[Get]]
函数会返回对象属性的值,该函数同时会考虑原型链上的继承属性。
综上,关于this
的取值:
- 函数中
this
的取值由调用者提供,由函数的当前调用方式决定 - 在函数调用括号
()
的左边如果是一个Reference
类型的值,那么this
的值将被设置为该值的base属性的值 - 所有其它情况(比如
()
左边的值不是Reference
类型),this
都将被设置为null
,因为null
没有任何意义,它们将会被隐式的转换成global object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
在上面的demo里
- eg1中调用
foo()
时,根据上面提到的原则,foo是一个变量,经过标识符解析会返回一个Reference
type的值fooReference,this被设置成fooReference对象的base属性的值–global
- 在eg2中调用
foo.bar()
时,bar作为foo的一个属性,经过属性读取(property access)会返回一个Reference
类型的值fooBarReference,this被设置成base属性的值–foo
- 在eg3中我们把foo.bar赋值给了test,test作为标识符,在调用test的时候产生了testReference,因此返回的就是global
现在理解了同一个函数,使用不同的方式调用,为什么返回值不同了。
来看两个问题,考虑下执行结果将是怎样的:
思考
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Function call and non-Reference type
上面提到过,当函数调用()
的左侧不是Reference类型值的时候,this将被设置为null,继而被隐式的转换成global。
non-Reference call
1 2 3 |
|
上面例子中()
的左侧是一个函数对象,既不是标识符也不是属性访问,因此不会返回Reference值,this将被设置为null,继而被转为global。
再来看几个复杂点的例子:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
相关推荐
本文详细介绍了 JavaScript 中 `this` 的用法及其取值规则。`this` 的值取决于函数的调用方式。在全局作用域和箭头函数中,`this` 的值取决于外层作用域的 `this` 值。掌握 `this` 的用法有助于开发者更好地理解 ...
总结,"table中checkbox取值"这一主题涉及到HTML元素结构、JavaScript和jQuery的操作、表单提交、前端状态管理和事件监听等多个知识点。熟练掌握这些技能,能帮助开发者更好地实现用户界面的交互功能,提高用户体验...
JavaScript中的树形结构是一种数据结构,它模仿了自然界中的树,具有层次分明的节点关系。在编程中,这种结构常用于表示目录结构、文件系统、组织关系或解析XML/JSON等复杂数据。在这个场景中,我们需要将一个用if、...
标题和描述均聚焦于FineReport报表工具中参数控件的取值与置数操作,这是一种在报表设计领域中实现动态参数交互的有效手段。FineReport,作为国内领先的报表开发工具,由南京帆软软件公司研发,提供了强大的报表设计...
var inputValue = $(this).val(); // 处理输入值 }); ``` 总之,jQuery提供了一套强大的工具来处理网页上的值和数据。正确理解和运用这些方法,可以极大地提高开发效率并减少代码量。无论是在获取表单元素的值,...
JavaScript 中的 call、apply、bind 方法是 Function 对象自带的三个方法,这三个方法的主要作用是转变函数中的 this 指向,从而可以达到“接花移木”的效果。下面将对这三个方法进行具体的讲解,并列出几个经典应用...
在Javascript中,this的取值取决于调用的模式。调用模式一共有四种:方法调用模式、函数调用模式、构造器调用模式和apply调用模式。 调用模式方法调用模式当一个函数被保存为对象的一个属性时,我们称它为一个方法。...
在本例中,我们关注的是如何使用JavaScript(JS)和Java来处理HTML表单中的复选框(checkbox)取值问题。复选框允许用户在多个选项中选择一个或多个。 1. **复选框取值** 复选框在HTML中通常使用`...
以下是一个简单的示例,展示了如何在JavaScript中创建一个对象,并通过循环和条件语句来模拟生命的不同阶段: ```javascript var life = {}; for (life.age = 1; life.age ; life.age++) { switch (life.age) { ...
箭头函数极大地简化了this的取值规则。 普通函数与箭头函数 普通函数指的是用function定义的函数: var hello = function () { console.log("Hello, Fundebug!"); } 箭头函数指的是用=>定义的函数: var hello...
### jQuery表单元素取值详解 #### 一、引言 在Web开发中,表单是用户与网站交互的重要组成部分。jQuery作为一种流行的JavaScript库,极大地简化了JavaScript编程,特别是DOM操作方面,使得开发者能够轻松地处理HTML...
在jQuery中,取值和赋值是基本的操作,以下将详细解释如何使用jQuery进行这些操作。 首先,获取和设置文本框(TEXTAREA)的值: ```javascript // 获取值 var textval = $("#text_id").attr("value"); // 或者 var ...
本文将详细讲解如何利用jQuery实现表格预览,并设置单元格选中及取值的功能。 首先,我们需要理解jQuery的核心概念。jQuery通过$函数作为入口,可以快速选择DOM元素并进行操作。例如,`$("table")`会选择页面上的...
var currentSelection = $(this).val(); console.log('当前选择:', currentSelection); // 在这里可以执行基于用户选择的操作 }); ``` 在这个事件处理器中,`currentSelection`会反映出用户最新的选择。 总结...
对象取值方法是JavaScript编程中不可或缺的一部分,理解和熟练掌握这些方法对于编写高效、健壮的代码至关重要。本篇文章将深入探讨JavaScript对象的取值方式及其相关知识点。 1. 点运算符(.) 点运算符是最常见也...
3. **在组件中取值**: - `computed`属性:Vue组件中的`computed`属性可以用来定义计算属性,这里的`value()`函数返回`$store.state.userData.xxx`,每次当`userData.xxx`的值发生变化时,`value`都会自动更新,...
layui 中的树形控件取值传值问题详解 layui 是一个流行的前端 JavaScript 库,提供了许多有用的控件和功能,其中树形控件是其中一个非常实用的控件。然而,在使用 layui 的树形控件时,开发者可能会遇到取值传值...
本主题聚焦于"jQuery表格预览设置单元格选中取值代码",这涉及到如何利用jQuery来实现对表格(Table)中的单元格(Cell)进行操作,包括选中和获取其值,以及可能的预览功能。这里我们将深入探讨相关的jQuery技术和...