JAVASCRIPT中THIS指的是什么?
这里是修真院前端小课堂,每篇分享文从
【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】
八个方面深度解析前端知识/技能,本篇分享的是:
【
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指的是什么?相关推荐
- 【转】JavaScript中的this关键字使用的四种调用模式
http://blog.csdn.net/itpinpai/article/details/51004266 this关键字 本意:这个.这里的意思. 在JavaScript中是指每一个方法或函数都会 ...
- 掌握JavaScript中的迭代器和生成器,顺便了解一下async、await的原理
掌握JavaScript中的迭代器和生成器,顺便了解一下async.await的原理 目录 掌握JavaScript中的迭代器和生成器,顺便了解一下async.await的原理 前言 1.迭代器(It ...
- JavaScript 中的作用域(scope)是指什么?
解释: 作用域Scope是你代码中的变量(variable),函数(function)和对象(object)在运行时(runtime)的可访问性(accessibility).换句话讲,作用域Scop ...
- javascript案例_如何在JavaScript中使用增强现实-一个案例研究
javascript案例 by Apurav Chauhan 通过Apurav Chauhan 如何在JavaScript中使用增强现实-一个案例研究 (How to use Augmented Re ...
- 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门)
by Preethi Kasireddy 通过Preethi Kasireddy 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门) (Why use stati ...
- [译]JavaScript中,{}+{}等于多少?
最近,Gary Bernhardt在一个简短的演讲视频"Wat"中指出了一个有趣的JavaScript怪癖:在把对象和数组混合相加时,会得到一些你意想不到的结果.本篇文章会依次讲解 ...
- JavaScript中实现函数重载和参数默认值
2019独角兽企业重金招聘Python工程师标准>>> 参数默认值是指在调用函数时,若省略了某个实参,函数会自动为该参数分配一个默认值,使得函数调用的方便性和灵活性大大提高. 举个例 ...
- 52 JavaScript中的正则表达式
技术交流QQ群:1027579432,欢迎你的加入! 欢迎关注我的微信公众号:CurryCoder的程序人生 1.什么是正则表达式 正则表达是(regular expression)是用于匹配字符串中 ...
- django中的for循环_深入了解 JavaScript 中的 for 循环
在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是: 简单for循环 for-in forEach 在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循 ...
最新文章
- 需求:整个网站不能出现以下两个链接。思路:检索到网站中凡是出现该链接的都让它的href值为空...
- 流式计算strom,Strom解决的问题,实现实时计算系统要解决那些问题,离线计算是什么,流式计算什么,离线和实时计算区别,strom应用场景,Strorm架构图和编程模型(来自学习资料)
- pyecharts学习(part2)--pyecharts Line
- 使用wxWidgets编程——第一步
- 营口理工学院计算机分数,营口理工学院历年分数线 2021营口理工学院录取分数线...
- cocos2D icon
- 动易html编辑器,解决动易后台编辑器(混合模式,编织模式不可用变灰
- 利用Scrapy爬取豆瓣电影
- css修改下拉框样式
- Android热修复之阿里Sophix的使用详解
- 爆破神器 Hydra 的使用
- C++知识讲解(二)
- u盘最大单个文件支持多少g_USB 文件传输单个文件最大能用多少G???
- PostgreSql增删改(与mysql差异)
- 【人月神话】浅谈人月神话0.1焦油坑
- python生成动态二维码
- Java判断字符串是否为数字(正负、小数)
- 设置TinyMCE在线HTML编辑控件只读
- Jenkins+Gitlab+Nginx+SonarQube+Maven编译Java项目自动发布与基于tag版本回退(重复构建问题已解决)
- 破解红蜘蛛 (破解红蜘蛛多媒体网络教室) 解除老师控制