---恢复内容开始---

this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要。接下来,笔者就从作用域的角度粗谈下自己对this关键字的理解,希望能给到大家一些启示,权当交流之用。

全局作用域中的this

本文将以作用域由外至内的方式逐步理解this关键字。首先,看下面这行代码:

console.log(this); // Window {top: Window, location: Location, document: document, window: Window, external: Object…}    Window全局对象

在浏览器中执行上面的语句后,我们将得到一个Window对象,这是一个全局对象。在全局作用域内,我们可以通过this访问到所有的全局属性。如下代码所示:

var a = 1;
console.log(this.a); //

函数作用域中的this

现在,我们将this关键字放到函数作用域中,测试代码如下:

var a = 1;
function test(){
var a = 2;
console.log(this.a); //
}
test();

我们可以看到此时打印出来的结果仍然是1,也就是说这时候this指向的还是全局对象。

这里也可以澄清的是,this并没有指向函数作用域(或者说是并没有指向函数作用域链中的活动对象,有关活动对象的概念可以参考JavaScript速记5 —— 执行环境、变量对象和作用域链),那么this是否会指向函数本身呢,我们接着来看下面一个例子:

var a = 1;
function test(){
var a = 2;
console.log(this.a); //
}
test.a = 3;
test();

通过上面的例子,我们知道this也并未指向函数本身。上面的例子中,this最终指向的都是全局对象,那么什么情况下this会指向其他对象呢,我们再来看下面的例子:

var a = 1;
function test(){
var a = 2;
console.log(this.a); //
}
var obj = {a: 3};
test.call(obj);

上面的例子中this指向了对象obj。既然只有当函数被调用时,才能确定this指向的对象,那么下一节我们就针对不同的函数调用方法下,逐一说明this的使用。

不同函数调用方法下的this

直接调用

var a = 1;
function test(){
console.log(this.a); //
}
test();

很明显,函数被直接调用是this指向的就是全局对象。

作为对象的方法调用

var a = 1;
function test(){
console.log(this.a); //
}
var obj = {a: 2, fn: test};
obj.fn();

当函数作为对象的方法被调用时,this指向当前调用该方法的对象。

作为构造函数调用

var a = 1;
function test(){
this.a = 2;
}
var obj = new test();
console.log(a); //
console.log(obj.a); //

通过上面的代码结果可以看到,全局对象中的属性a并没有被改变,此时this指向该构造函数创建的对象。

通过call或apply方法调用

call和apply都是Function对象的方法,都可以用来动态改变this的指向,达成函数复用的目的。这里笔者不在详细介绍这两个方法,有兴趣的读者可以参考相关文章。需要特别说明的是,这两个方法的第一个参数就是this。由于这两个方法的用法类似,这里我们仅以call方法为例。上例子:

var a = 1;
function test(){
console.log(this.a); //
}
test.call();

call方法的第一个参数是this,在没有实参的情况下,上面例子中this默认指向的对象就是全局对象。我们再来看一个例子:

var a = 1;
function test(){
console.log(this.a); //
}
var obj = {a: 2, fn: test};
obj.fn.call();

上面的例子进一步证明了,即便使用对象的方法调用call,this默认指向的依旧是全局对象。为了改变this的指向,我们需要显式的传递第一个参数过去,如下代码:

var a = 1;
function test(){
console.log(this.a); //
}
var obj = {a: 2};
test.call(obj);

嵌套函数作用域中的this

文章的最后我们再来看一下嵌套函数中的this引用。示例代码如下:

var a = 1;
function test(){
console.log(this.a); //
function test2(){
console.log(this.a); //
}
test2();
}
var obj = {a: 2, fn: test};
obj.fn();

上面的例子说明,嵌套函数被调用是并没有继承被嵌套函数的this引用,在嵌套函数被调用时,this指向全局对象。在有些应用中,我们需要在嵌套函数中读取调用被嵌套函数的对象的属性,此时可以声明一个局部变量保存this引用,代码如下所示:

var a = 1;
function test(){
console.log(this.a); //
var self = this;
function test2(){
console.log(self.a); //
}
test2();
}
var obj = {a: 2, fn: test};
obj.fn();

---恢复内容结束---

this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要。接下来,笔者就从作用域的角度粗谈下自己对this关键字的理解,希望能给到大家一些启示,权当交流之用。

全局作用域中的this

本文将以作用域由外至内的方式逐步理解this关键字。首先,看下面这行代码:

console.log(this); // Window {top: Window, location: Location, document: document, window: Window, external: Object…}    Window全局对象

在浏览器中执行上面的语句后,我们将得到一个Window对象,这是一个全局对象。在全局作用域内,我们可以通过this访问到所有的全局属性。如下代码所示:

var a = 1;
console.log(this.a); //

函数作用域中的this

现在,我们将this关键字放到函数作用域中,测试代码如下:

var a = 1;
function test(){
var a = 2;
console.log(this.a); //
}
test();

我们可以看到此时打印出来的结果仍然是1,也就是说这时候this指向的还是全局对象。

这里也可以澄清的是,this并没有指向函数作用域(或者说是并没有指向函数作用域链中的活动对象,有关活动对象的概念可以参考JavaScript速记5 —— 执行环境、变量对象和作用域链),那么this是否会指向函数本身呢,我们接着来看下面一个例子:

var a = 1;
function test(){
var a = 2;
console.log(this.a); //
}
test.a = 3;
test();

通过上面的例子,我们知道this也并未指向函数本身。上面的例子中,this最终指向的都是全局对象,那么什么情况下this会指向其他对象呢,我们再来看下面的例子:

var a = 1;
function test(){
var a = 2;
console.log(this.a); //
}
var obj = {a: 3};
test.call(obj);

上面的例子中this指向了对象obj。既然只有当函数被调用时,才能确定this指向的对象,那么下一节我们就针对不同的函数调用方法下,逐一说明this的使用。

不同函数调用方法下的this

直接调用

var a = 1;
function test(){
console.log(this.a); //
}
test();

很明显,函数被直接调用是this指向的就是全局对象。

作为对象的方法调用

var a = 1;
function test(){
console.log(this.a); //
}
var obj = {a: 2, fn: test};
obj.fn();

当函数作为对象的方法被调用时,this指向当前调用该方法的对象。

作为构造函数调用

var a = 1;
function test(){
this.a = 2;
}
var obj = new test();
console.log(a); //
console.log(obj.a); //

通过上面的代码结果可以看到,全局对象中的属性a并没有被改变,此时this指向该构造函数创建的对象。

通过call或apply方法调用

call和apply都是Function对象的方法,都可以用来动态改变this的指向,达成函数复用的目的。这里笔者不在详细介绍这两个方法,有兴趣的读者可以参考相关文章。需要特别说明的是,这两个方法的第一个参数就是this。由于这两个方法的用法类似,这里我们仅以call方法为例。上例子:

var a = 1;
function test(){
console.log(this.a); //
}
test.call();

call方法的第一个参数是this,在没有实参的情况下,上面例子中this默认指向的对象就是全局对象。我们再来看一个例子:

var a = 1;
function test(){
console.log(this.a); //
}
var obj = {a: 2, fn: test};
obj.fn.call();

上面的例子进一步证明了,即便使用对象的方法调用call,this默认指向的依旧是全局对象。为了改变this的指向,我们需要显式的传递第一个参数过去,如下代码:

var a = 1;
function test(){
console.log(this.a); //
}
var obj = {a: 2};
test.call(obj);

嵌套函数作用域中的this

文章的最后我们再来看一下嵌套函数中的this引用。示例代码如下:

var a = 1;
function test(){
console.log(this.a); //
function test2(){
console.log(this.a); //
}
test2();
}
var obj = {a: 2, fn: test};
obj.fn();

上面的例子说明,嵌套函数被调用是并没有继承被嵌套函数的this引用,在嵌套函数被调用时,this指向全局对象。在有些应用中,我们需要在嵌套函数中读取调用被嵌套函数的对象的属性,此时可以声明一个局部变量保存this引用,代码如下所示:

var a = 1;
function test(){
console.log(this.a); //
var self = this;
function test2(){
console.log(self.a); //
}
test2();
}
var obj = {a: 2, fn: test};
obj.fn();

浅谈js中的this关键字的更多相关文章

  1. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

  2. 浅谈Java中的final关键字

    浅谈Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  3. 浅谈JS中的!=、== 、!==、===的用法和区别 JS中Null与Undefined的区别 读取XML文件 获取路径的方式 C#中Cookie,Session,Application的用法与区别? c#反射 抽象工厂

    浅谈JS中的!=.== .!==.===的用法和区别   var num = 1;     var str = '1';     var test = 1;     test == num  //tr ...

  4. 浅谈JS中 var let const 变量声明

    浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...

  5. 由项目浅谈JS中MVVM模式

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.    背景 最近项目原因使用了durandal.js和knock ...

  6. js架构设计模式——由项目浅谈JS中MVVM模式

    1.    背景 最近项目原因使用了durandal.js和knockout.js,颇有受益.决定写一个比较浅显的总结. 之前一直在用SpringMVC框架写后台,前台是用JSP+JS+标签库,算是很 ...

  7. 浅谈js中的数据类型,使用typeof获取js数据类型

    JS中的数据类型 1):Undefined——值未定义 注:Undefined类型只有一个值,即特色的undefined.在使用var声明变量但未对其加以初始化时,这个变量的值就是undefined ...

  8. 浅谈js中的浅拷贝和深拷贝

    在js中如何把一个对象里的属性和方法复制给另一个对象呢? 下面举一个例子来说明: var person={name:'chen',age:18}; var son={sex:'男'}; functio ...

  9. 浅谈JS中的高级函数

    在JavaScript中,函数的功能十分强大.它们是第一类对象,也可以作为另一个对象的方法,还可以作为参数传入另一个函数,不仅如此,还能被一个函数返回!可以说,在JS中,函数无处不在,无所不能,堪比孙 ...

随机推荐

  1. java中split特殊符号

    关于点的问题是用string.split("[.]") 解决. 关于竖线的问题用 string.split("\\|")解决. 关于星号的问题用 string. ...

  2. C#深度学习の接口传参(interface)-----接口的妙用

    一.接口可以干嘛 我们知道,接口的本质是一个约束规范,委托是方法纵向(形式上)的封装,接口是不同方法横向(广度)的封装 接口中不能有变量,但是可以有属性方法.常见的,我们可以用接口: 1.实现需求方的 ...

  3. Mac下的效率工具autojump

    (转) IDE 用起来总是得不到满足,Mac 适合搞开发,我也十分喜欢 Mac 系统,当然可以说喜欢 Unix/Linux 系统.今天在 .zshrc 文件中添加了这么几行快捷命令: alias go ...

  4. python新式类与旧式类

    python2.X是经典类[旧式类]: 是以深度优先[] 但是在Python2.x中,默认都是经典类,只有显式继承了object才是新式类,即:class Person(object):pass 新式 ...

  5. React-关于react的思考

    声明式开发 减少dom操作,减少代码量 可以与其他框架并存 组件化开发 单向数据流 视图层框架 大型项目需要与其他数据层框架一起使用 函数式编程 方便自动化测试

  6. FineUI十周年纪念版即将发布(基于像素的响应式布局,独此一家)!

    [新版预报]FineUI十周年纪念版(v5.0.0)即将于2018-04-23发布! 官网示例已更新:http://pro.fineui.com/ 特别助攻:基于像素的响应式布局,FineUI独家秘笈 ...

  7. IS创新之路 -- 都昌公司赋能型HIT企业发展之路

    ◆◆前言 近日,上海瑞金医院对我司表示:“我院从2000年开始自主开发医院信息系统,走出了一条可持续的信息化发展之路.已建成五大系统,284个子系统.但我院仍然坚持在努力推进以电子病历为核心医院信息化 ...

  8. MySQL备份恢复-mysqldump原理

    +++++++++++++++++++++++++++++++++++++++++++标题:mysqldump对MySQL数据库备份恢复原理时间:2019年2月23日内容:mysqldump工具重点: ...

  9. windows 比较文件命令--fc

    dos环境下的比较文件命令 win7帮助 D:\test>fc /? 比较两个文件或两个文件集并显示它们之间 的不同 FC [/A] [/C] [/L] [/LBn] [/N] [/OFF[LI ...

  10. rocketmq双主模式

    1.官网 https://rocketmq.apache.org/ 官方安装文档 https://rocketmq.apache.org/docs/quick-start/ 2.rocketmq多主配 ...