这里是修真院前端小课堂,每篇分享文从

【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】

八个方面深度解析前端知识/技能,本篇分享的是:

JAVASCRIPT中THIS指的是什么?

(1)背景介绍:

JAVASCRIPT中THIS指的是什么?

this是JavaScript语言中定义的众多关键字之一,它的特殊在于它自动定义于每一个函数域内,在函数运行时,

this会自动生成一个内部对象,这个对象只能在函数内部使用。同时,随着函数使用场合的不同,this的值会发生变化。

但是有一个总的原则,那就是this指的是,调用函数的那个对象。

它是一个很特别的关键字,被自动定义在所有函数的作用域中

在JavaScript中,this是动态绑定的,它可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。

这就导致了this具备了多重含义,可以使得JavaScript更灵活的使用。

(2)知识剖析:

作为对象方法调用

在 JavaScript 中,函数也是对象,因此函数可以作为一个对象的属性,此时该函数被称为该对象的方法,在使用这种调用方式时,this 被自然绑定到该对象。

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 对象

作为函数调用

函数也可以直接被调用,此时 this 绑定到全局对象。在浏览器中,window 就是该全局对象。比如下面的例子:

函数被调用时,this 被绑定到全局对象,接下来执行赋值语句,相当于隐式的声明了一个全局变量,这显然不是调用者希望的。

function makeNoSense(x) {

this.x = x;

}

makeNoSense(5);

x;// x 已经成为一个值为 5 的全局变量

对于内部函数,即声明在另外一个函数体内的函数,这种绑定到全局对象的方式会产生另外一个问题。我们仍然以前面提到的 point 对象为例,

这次我们希望在 moveTo 方法内定义两个函数,

分别将 x,y 坐标进行平移。结果可能出乎大家意料,不仅 point 对象没有移动,反而多出两个全局变量 x,y。

var point = {

x : 0,

y : 0,

moveTo : function(x, y) {

// 内部函数

var moveX = function(x) {

this.x = x;//this 绑定到了哪里?

};

// 内部函数

var moveY = function(y) {

this.y = y;//this 绑定到了哪里?

};

moveX(x);

moveY(y);

}

};

point.moveTo(1, 1);

point.x; //==>0

point.y; //==>0

x; //==>1

y; //==>1

这属于 JavaScript 的设计缺陷,正确的设计方式是内部函数的 this 应该绑定到其外层函数对应的对象上,

为了规避这一设计缺陷,聪明的 JavaScript 程序员想出了变量替代的方法,约定俗成,该变量一般被命名为 that。

var point = {

x : 0,

y : 0,

moveTo : function(x, y) {

var that = this;

// 内部函数

var moveX = function(x) {

that.x = x;

};

// 内部函数

var moveY = function(y) {

that.y = y;

}

moveX(x);

moveY(y);

}

};

point.moveTo(1, 1);

point.x; //==>1

point.y; //==>1

作为构造函数调用

JavaScript 支持面向对象式编程,与主流的面向对象式编程语言不同,JavaScript 并没有类(class)的概念,

而是使用基于原型(prototype)的继承方式。相应的,JavaScript 中的构造函数也很特殊,如果不使用 new 调用,则和普通函数一样。

作为又一项约定俗成的准则,构造函数以大写字母开头,提醒调用者使用正确的方式调用。如果调用正确,this 绑定到新创建的对象上。

function Point(x, y){

this.x = x;

this.y = y;

}

使用 apply 或 call 调用

让我们再一次重申,在 JavaScript 中函数也是对象,对象则有方法,apply 和 call 就是函数对象的方法。

这两个方法异常强大,他们允许切换函数执行的上下文环境(context),即 this 绑定的对象。很多 JavaScript 中的技巧以及类库都用到了该方法。

function Point(x, y){

this.x = x;

this.y = y;

this.moveTo = function(x, y){

this.x = x;

this.y = y;

}

}

var p1 = new Point(0, 0);

var p2 = {x: 0, y: 0};

p1.moveTo(1, 1);

p1.moveTo.apply(p2, [10, 10]);

在上面的例子中,我们使用构造函数生成了一个对象 p1,该对象同时具有 moveTo 方法;使用对象字面量创建了另一个对象 p2,

我们看到使用 apply 可以将 p1 的方法应用到 p2 上,这时候 this 也被绑定到对象 p2 上。另一个方法 call 也具备同样功能,

不同的是最后的参数不是作为一个数组统一传入,而是分开传入的。

(3)常见问题:

this碰到return的时候

(4)解决方案:

先看几个demo

function halo()

{

this.user = 'joker';

return {};

}

var a = new halo;

console.log(a.user); //undefined

//

function halo()

{

this.user = 'joker';

return function(){};

}

var a = new halo;

console.log(a.user); //undefined

//

function halo()

{

this.user = 'joker';

return 1;

}

var a = new halo;

console.log(a.user); //joker

//

function halo()

{

this.user = 'joker';

return undefined;

}

var a = new halo;

console.log(a.user); //joker

//undefined

function halo()

{

this.user = 'joker';

return undefined;

}

var a = new halo;

console.log(a); //fn {user: "joker"}

//null

function halo()

{

this.user = 'joker';

return null;

}

var a = new halo;

console.log(a.user); //joker

如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

(5)编码实战:

见上面demo

(6)拓展思考:

为什么 this 在 JavaScript 中的含义如此丰富?

JavaScript 中的函数既可以被当作普通函数执行,也可以作为对象的方法执行,这是导致 this 含义如此丰富的主要原因。

一个函数被执行时,会创建一个执行环境(ExecutionContext),函数的所有的行为均发生在此执行环境中,

构建该执行环境时,JavaScript 首先会创建 arguments变量,其中包含调用函数时传入的参数。接下来创建作用域链。然后初始化变量,

首先初始化函数的形参表,值为 arguments变量中对应的值,如果 arguments变量中没有对应值,则该形参初始化为 undefined。

如果该函数中含有内部函数,则初始化这些内部函数。如果没有,继续初始化该函数内定义的局部变量,

需要注意的是此时这些变量初始化为 undefined,其赋值操作在执行环境(ExecutionContext)创建成功后,函数执行时才会执行,

这点对于我们理解 JavaScript 中的变量作用域非常重要,鉴于篇幅,我们先不在这里讨论这个话题。最后为 this变量赋值,

如前所述,会根据函数调用方式的不同,赋给 this全局对象,当前对象等。至此函数的执行环境(ExecutionContext)创建成功,

函数开始逐行执行,所需变量均从之前构建好的执行环境(ExecutionContext)中读取。

(7)参考文献:

参考

(8)更多讨论:

Q1:setTimeout、setInterval中的this是指向哪里?

A1:超时调用的代码都是在全局执行域中执行的”。setTimeout/setInterval 执行的时候,this 默认指向 window 对象,除非手动改变 this 的指向。

Q2:如何改变this的指向?

A2:

可以使用call或者apply的方法改变指向

如果xxxx.call(a),this就指向a;当a为null或者undefined的时候,会指向window; 假如说要传参,构造函数名.call("a","b",“c”),它的第一个参数传到的是this;apply类似,但是与之不同的是,要书写成: 构造函数名.apply("a",["b","c"])的形式,这就是差别;

Q3:箭头函数中this指向
A3:箭头函数中的this是在定义函数的时候绑定,而不是在执行函数的时候绑定。所谓的定义时候绑定,就是this是继承自父执行上下文!!中的this 。

箭头函数中,this指向的固定化,并不是因为箭头函数内部有绑定this的

机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外

层代码块的this。正是因为它没有this,所以也就不能用作构造函数。

JAVASCRIPT中THIS指的是什么?相关推荐

  1. 【转】JavaScript中的this关键字使用的四种调用模式

    http://blog.csdn.net/itpinpai/article/details/51004266 this关键字 本意:这个.这里的意思. 在JavaScript中是指每一个方法或函数都会 ...

  2. 掌握JavaScript中的迭代器和生成器,顺便了解一下async、await的原理

    掌握JavaScript中的迭代器和生成器,顺便了解一下async.await的原理 目录 掌握JavaScript中的迭代器和生成器,顺便了解一下async.await的原理 前言 1.迭代器(It ...

  3. JavaScript 中的作用域(scope)是指什么?

    解释: 作用域Scope是你代码中的变量(variable),函数(function)和对象(object)在运行时(runtime)的可访问性(accessibility).换句话讲,作用域Scop ...

  4. javascript案例_如何在JavaScript中使用增强现实-一个案例研究

    javascript案例 by Apurav Chauhan 通过Apurav Chauhan 如何在JavaScript中使用增强现实-一个案例研究 (How to use Augmented Re ...

  5. 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门)

    by Preethi Kasireddy 通过Preethi Kasireddy 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门) (Why use stati ...

  6. [译]JavaScript中,{}+{}等于多少?

    最近,Gary Bernhardt在一个简短的演讲视频"Wat"中指出了一个有趣的JavaScript怪癖:在把对象和数组混合相加时,会得到一些你意想不到的结果.本篇文章会依次讲解 ...

  7. JavaScript中实现函数重载和参数默认值

    2019独角兽企业重金招聘Python工程师标准>>> 参数默认值是指在调用函数时,若省略了某个实参,函数会自动为该参数分配一个默认值,使得函数调用的方便性和灵活性大大提高. 举个例 ...

  8. 52 JavaScript中的正则表达式

    技术交流QQ群:1027579432,欢迎你的加入! 欢迎关注我的微信公众号:CurryCoder的程序人生 1.什么是正则表达式 正则表达是(regular expression)是用于匹配字符串中 ...

  9. django中的for循环_深入了解 JavaScript 中的 for 循环

    在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是: 简单for循环 for-in forEach 在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循 ...

最新文章

  1. 需求:整个网站不能出现以下两个链接。思路:检索到网站中凡是出现该链接的都让它的href值为空...
  2. 流式计算strom,Strom解决的问题,实现实时计算系统要解决那些问题,离线计算是什么,流式计算什么,离线和实时计算区别,strom应用场景,Strorm架构图和编程模型(来自学习资料)
  3. pyecharts学习(part2)--pyecharts Line
  4. 使用wxWidgets编程——第一步
  5. 营口理工学院计算机分数,营口理工学院历年分数线 2021营口理工学院录取分数线...
  6. cocos2D icon
  7. 动易html编辑器,解决动易后台编辑器(混合模式,编织模式不可用变灰
  8. 利用Scrapy爬取豆瓣电影
  9. css修改下拉框样式
  10. Android热修复之阿里Sophix的使用详解
  11. 爆破神器 Hydra 的使用
  12. C++知识讲解(二)
  13. u盘最大单个文件支持多少g_USB 文件传输单个文件最大能用多少G???
  14. PostgreSql增删改(与mysql差异)
  15. 【人月神话】浅谈人月神话0.1焦油坑
  16. python生成动态二维码
  17. Java判断字符串是否为数字(正负、小数)
  18. 设置TinyMCE在线HTML编辑控件只读
  19. Jenkins+Gitlab+Nginx+SonarQube+Maven编译Java项目自动发布与基于tag版本回退(重复构建问题已解决)
  20. 破解红蜘蛛 (破解红蜘蛛多媒体网络教室) 解除老师控制

热门文章

  1. 重新启动mysql服务器
  2. tqdm的使用和例子
  3. 程序员搞开源,读什么书最合适?
  4. 平面四连杆运动方程分析with matlab
  5. 英伟达gt和gtx的区别
  6. 为什么要用花焊盘?全连接和花连接有什么区别?梅花焊盘和泪滴焊盘各有什么作用?
  7. mysql中如何选中数据库_MySQL 选择数据库
  8. 鸿蒙os第一批到第四批要多久,鸿蒙值得期待 鸿蒙OS系统适应计划曝光
  9. C++:Error C 1010:在查找预编译头时遇到意外的文件结尾。
  10. Xcode中的隐藏宝藏:模拟器里如何快速预览动态字体显示效果