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

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. C#的自动拼接Sql语句Insert方法及思路

    思路: 1.想想插入语句,大概是这样的一个框架:INSERT INTO 表名 (数据库列名) values (值) 2.这里要3个变量是不固定的,分别是:表名.数据库列名.值: a.表名我们这里很容易 ...

  2. VSCode的Python扩展下程序运行的几种方式与环境变量管理

    在VSCode中编写Python程序时,由于有些地方要使用环境变量,但是发现设置的环境变量有时不起作用,花了点时间研究了一下,过程不表,直接说结论. 首先,环境变量的设置,Python扩展中有三种方式 ...

  3. swift修改UITextfield的Placeholder字体大小和颜色

    第一种方法: self.userNumber.setValue(UIColor.lightGray, forKey: "_placeholderLabel.textColor") ...

  4. C++调用Opencv实践中遇到的问题备忘录

    1.编写一个显示图片的项目,但显示的图片全灰色. 原因:需要在imshow()函数前加一个namedWindow()函数.https://blog.csdn.net/mao_hui_fei/artic ...

  5. new 和 newInstance 的区别

    初始化一个类,生成一个实例的时候:newInstance() 和 new 有什么区别? 用newInstance与用new是区别的,区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会有两 ...

  6. 替换空格[by Python]

    题目: 请实现一个函数,将一个字符串中的空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 1.使用python自带的repla ...

  7. day6-基础函数的学习(一)

    今日份目录 1.函数的定义 2.函数的返回值 3.函数的参数 4.函数的局部变量与全局变量 5.名称空间与作用域 6.global与nonlocal 7.高阶函数 继续今日份总结!这个总结也晚了,哎, ...

  8. (四)Exploring Your Cluster

    The REST API Now that we have our node (and cluster) up and running, the next step is to understand ...

  9. 2.[Andriod]Andriod Studio结合Visual Studio Emulator for Android调试Android App

    0. 工欲善其事必先利其器 上一篇博客对比了一下Android和WinPhnoe的布局容器,后续篇章重点放在Android的开发上了. 说到开发就绕不开调试程序,调试Android App我们有2种选 ...

  10. Luogu4755 Beautiful Pair 最值分治、主席树

    传送门 整天做一些模板题感觉药丸 设\(val_i\)表示第\(i\)个位置的值 看到区间最大值考虑最值分治.对于当前的区间\([l,r]\),找到区间最大值\(mid\),递归\([l,mid-1] ...