在很多编程语言中都有this这个特殊关键字的存在,比如Java中的this,还有本文要说到的JavaScript中的this。那么,JavaScript中this究竟有什么特性和用法呢?它又是如何定义的呢?

先来看看ECMAScript 标准规范对this 的定义:

「The this keyword evaluates to the value of the ThisBinding of the current execution context.」
「this 这个关键字代表的值为当前执行上下文的ThisBinding。」

然后再来看看MDN 对this 的定义:

「In most cases, the value of this is determined by how a function is called.」
「在大多数的情况下,this 其值取决于函数的调用方式。」

而JavaScript中this有个有趣的特性,就是它不是固定不变的,它会随着执行环境的改变而改变  大致如下

  ①在函数(方法)被调用时,在方法中的this 表示始终指向最后调用该方法时的那个对象;

  

   在上面的例子中可以看出当全局环境下定义了和对象obj上属性同名的变量时,在对象上的方法被调用的会先在方法作用域内查找需要的变量如name、fn,如果能够找到就取值使用,找不到就沿着作用域链往创建这个方法fn的那个作用域obj去查找,如此一层一层网上一直找到最顶层的window为止。但是本例子关注的是this的指向,通过打印知道是指向了obj,而调用对象方法fn最近也就是最后的那个对象刚好就是obj,因此佐证了this的通俗定义【始终指向最后调用该方法的那个对象】。

  另外在本例子中可能还会有人疑惑为何obj方法fn里面的name打印出来不是obj的那个name值123,反而是全局变量的2333?这里解释一下,首先我们知道要访问一个对象上的属性,规定的格式是 obj.属性或者obj[属性]。而此时打印的name并没有obj,因此会被当成一个变量去解析,这时候会在fn函数作用域查找有没有name变量,没有就往作用域链一层一层往上找(也有人认为是当没有明确的调用对象比如obj时,this直接指向了window对象)。此时的作用域链是这样子的:obj._proto_===window.prototype===window._proto_ ,根据这个作用域链最终找到了window的对象原型上有name这个变量,这就找到了!

  ②在全局环境中,无论是否是在严格模式下,this 都是指向全局对象,在浏览器中指向 window 对象,在Nodejs中的Global对象,在严格模式下指向的是undefined,因此严格模式下定义的全局变量在调用时就不可以使用this调用;

1 var num = 123;
2 console.log(this.num ) ; // 123
3 console.log(this.num === num ) ; // true
4 console.log(this === window) ; // true

严格模式下:

"use strict"     // 使用严格模式
var num= 123; function fn() {
console.log(this); // undefined
console.log(this.num); // 报错 "Cannot read property 'num' of undefined",因为此时 this 是 undefined
} fn();

  ③在构造函数中,this就是被指向通过构造方法创建的那个实例对象。

 1 var name="JavaScript";
2
3 function Student(sName,sAge){
4 this.name=sName;
5 this.age=sAge;
6 console.log(this); //打印实例对象Student{name:"张三",18}和Student{name:"李四",20}
7 }
8
9 var s1=new Student("张三",18);
10 var s2=new Student("李四",20);

  以上都是讲了怎么讲this的指向的那个对象找出来,以便达到我们使用对象上的属性和方法的目的。然而,this的指向还可以人为地手动通过call、apply、bind这三个方法进行改变,这样有时候能满足某个方法里直接使用this重新指向的那个对象obj上的方法和属性,但是又不改变方法原来的对象。

  从上图打印可以看出call将原来ok方法this的指向由obj变为newObj,这样ok方法就可以使用newObj对象上的属性和方法了,而第17行的打印输出说明原对象obj上的属性方法并没有被破坏。

  call、apply、bind三个方法实现的功能(都是用来扩充函数运行时的作用域)是一样的,最后顺便补充说说三者之间的写法上一些小区别:

    1)、bind()方法会返回一个函数,将接受多个参数的函数变换成接受一个单一参数。

      注意:bind(thisArg[, arg1[, arg2[, ...]]]), 将接受多个参数的函数变换成接受一个单一参数。bind()方法所返回的函数的length(形参数量)等于原函数的形参数量减去传入bind()方法中的实参数量(第一个参数以后的所有参数),因为传入bind中的实参都会绑定到原函数的形参。

    2)、apply()方法 接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。

      注意:apply([thisObj [,argArray] ]),调用一个对象的一个方法,2另一个对象替换当前对象。如果argArray不是一个有效数组或不是arguments对象,那么将导致一个TypeError,如果没有提供argArray和thisObj任何一个参数,那么Global对象将用作thisObj。

    3)、call()方法 第一个参数和apply()方法的一样,但是传递给函数的参数必须列举出来。

      注意:call([thisObject[,arg1 [,arg2 [,...,argn]]]]);,应用某一对象的一个方法,用另一个对象替换当前对象。call方法可以用来代替另一个对象调用一个方法,call方法可以将一个函数的对象上下文从初始的上下文改变为thisObj指定的新对象,如果没有提供thisObj参数,那么Global对象被用于thisObj。

  【三个方法记忆小窍门】call就像打电话召集需要的参数,一个一个跟在thisObj后面,apply就像填表格申请某样东西一样把需要的参数打包在一个数组里,bind是把参数一个一个捆绑装订在thisObj后面,跟call类似,但最后bind只返回一个函数,还需要自己手动调用一下(像快递员集中揽件后还要发货一样)。这三个方法如果用在定时器的匿名回调函数中时有破坏定时器的效果,因为他们会立即执行!

   ④都说ES6大法好,那么this在ES6中又是如何表现的呢?ES6带来的箭头函数让开发者眼前一亮的不止代码写法更简洁优雅了,还让函数中飘忽不定的this有了官方指定的去处!

  在箭头函数中,this区别于传统的普通函数中的this,普通函数中this指向的是最后调用函数的那个对象(也就是函数被调用运行时的对象);而箭头函数的this却是在定义箭头函数时由外层函数的this“继承”(不是真正的继承,有点像借用更合适)过来的,换句话说就是实际上箭头函数自身并没有this,它依赖的是外层代码定义时那个this。箭头函数的this不是调用的时候决定的,而是在定义的时候包含着箭头函数的对象就是它的this。这里面其实也应该包含一个查找过程,如下:箭头函数的this看外层的是否有函数,如果有,外层函数的this就是内部箭头函数的this,如果没有,则this是window

情景一:箭头函数的外层是函数,此时的外层函数是由obj最后调用了,于是this指向了obj,箭头函数“继承”了它。

情景二:对象上的方法直接定义为箭头函数时,由于箭头函数外层是对象,不是一个函数,此时this直接指向了window。

  箭头函数带来便捷的同时也有一些需要留意的点,如下:

①在箭头函数中使用call、apply、bind时this参数绑定失效了,this被强制指向了window,至于原因本人尚未清楚,如有人知道可以在评论告知,不甚感激。  

 1 var name="Hello watching me!";
2 var obj={
3 name:"coder4web",
4 arrowFn:()=>{ //直接将对象属性设置为箭头函数情况
5 console.log("this===newObj的结果是:"+(this===newObj));
6 console.log("this===obj的结果是:"+(this===obj));
7 console.log(this.name+"--is testing :I'm an arrow function!");
8 }
9 };
10 var newObj={
11 name:123,
12 ok:function(){
13 console.log("哈哈哈哈~~");
14 }
15 };
16 // obj.arrowFn.apply();
17 // obj.arrowFn.apply(undefined);
18 // obj.arrowFn.apply(null);
19 obj.arrowFn.apply(newObj); //这4种方式的效果是一样的

②箭头函数不能作为构造函数,因为箭头函数都是匿名函数,而构造函数是具名函数,因此箭头函数也不能使用new,箭头函数也不能用argument,没有prototype属性。

 1 var Student=(name)=>{
2 this.name=name;
3 }
4 // var s=new Student("李雷");
5 // console.log(s); //Uncaught TypeError: Student is not a constructor
6
7 var fn=(x)=>{
8 console.log(x);
9 // console.log(arguments); //Uncaught ReferenceError: arguments is not defined
10 }
11 // fn(11);
12
13 var t1=function(){}
14 var t2=function teacher(){}
15 var t3=()=>{}
16 console.log(t1);
17 console.log(t1.prototype);
18 console.log(t2);
19 console.log(t2.prototype);
20 console.log(t3);
21 console.log(t3.prototype);

  至此,JavaScript中的this指向问题探究完毕,以上内容的大部分结论都是阅读思考后自己的总结,鉴于水平有限难免有认识上误差,如果有更好的见解,欢迎在评论区指正提建议哦!谢谢大家的阅读~

  本文属于本人在博客园的第一篇原创文章,希望是个好的开始,一起加油!

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

JavaScript的this到底代表谁?(this指向哪里?)的更多相关文章

  1. javascript的this分别代表什么

    鉴于大家对this到底代表的是什么有疑问,现在将我个人理解的this的情况整理如下.有错误请指正. 第一种情况:  如果是一个全局的function,则this相当于window对象. 这个打印出来的 ...

  2. 基于JavaScript判断浏览器到底是关闭还是刷新(超准确)

    这篇文章主要介绍了基于JavaScript判断浏览器到底是关闭还是刷新(超准确)的相关资料,需要的朋友可以参考下 本文是小编总结的一些核心内容,个人感觉对大家有所帮助,具体内容请看下文: 页面加载时只 ...

  3. 百度蜘蛛IP地址到底代表什么含义?

    百度蜘蛛IP地址到底代表什么含义,是不是不同的ip地址所代表的含义不一样呢?对权重和抓取是否有影响?哪些是无效的蜘蛛,哪些是站长工具的蜘蛛,那些又是百度自己真正的蜘蛛?百度蜘蛛,是百度搜索引擎的一个自 ...

  4. javaScript中this到底指向谁

    1.前言 在JavaScript中,this的指向一直是大多数初学者的易错点,总是搞不清楚this到底指向谁,而在求职面试中,this的指向问题往往又是高频考点.本篇博文就来总结一下在JavaScri ...

  5. JavaScript初探系列(五)——this指向

    一.涵义 this关键字是一个非常重要的语法点.毫不夸张地说,不理解它的含义,大部分开发任务都无法完成.this可以用在构造函数之中,表示实例对象.除此之外,this还可以用在别的场合.但不管是什么场 ...

  6. JavaScript 函数参数传递到底是值传递还是引用传递

    tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里 ...

  7. JavaScript的“闭包”到底是什么

    在JavaScripot函数闭包的定义中,一般都有一个outer 函数,一个inner函数.那么“闭包”到底是指outer函数呢,还是指inner函数? 从官方定义来看,并不清楚:A closure  ...

  8. javascript DOM,它到底是什么-------Day32

    这一晚上看的我是头疼不已啊,为什么呢? 终究是半路出家,我对javascript的理解仅仅停留在:调用javascript,改变页面样式,元素和实现一些事件的响应,尽管须要的时候可能会用,可是到底使用 ...

  9. 「MYSQL」MYSQL中的int(11)到底代表什么意思?

    一.前言 在工作中经常要与mysql打交道,但是对mysql的各个字段类型一直都是一知半解,因此写本文总结记录一番. 二.简介 对于int类型的一些基础知识其实上图已经说的很明白了,在这里想讨论下常用 ...

随机推荐

  1. 深入了解Redis(3)-对象

    Redis主要的数据结构有简单动态字符串(SDS).双端链表.字典.压缩列表.整数集合,等等.但Redis并没有直接使用这些数据结构来实现键值对数据库, 而是基于这些数据结构创建了一个对象系统, 这个 ...

  2. ZERO:新手应该如何学习SEO优化

    http://www.wocaoseo.com/thread-325-1-1.html 有一个10000小时理论,说是在各行各业,想成为大师级的人物就要付出10000小时的努力,在SEO这边也是如此. ...

  3. SEO大神都是些什么人

    http://www.wocaoseo.com/thread-97-1-1.html 貌似好久没有更新seo培训联盟的文章了,最近一直在专心学习其他的东西,前一段写了几篇关于用户需求和体验的文章,但是 ...

  4. CCAI观后

    暑期和大老板的学生一起学了一暑假的计算机视觉和机器学习,以前只是在京畿范围的学校听到的报告和这阵的学习数量级都不同.当时看到了很多人的报告,忽然发现了做报告应该做的准备实际还有很多. 首先是要有充分的 ...

  5. 构建docker私有仓库+k8s-pod应用

    环境版本系统:centos7.4docker-compose version 1.26.2docker-py version: 4.3.0CPython version: 2.7.5docker-ve ...

  6. day43:CSS样式相关

    目录 1.高度和宽度 2.字体相关 3.字体对齐 4.颜色设置 5.背景 6.边框 7.盒子模型 8.display属性 9.伪元素选择器 10.伪类选择器 11.浮动 12.文字装饰 13.相对定位 ...

  7. Python爬虫实战点触验证码, 模拟登陆bilibili

    爬虫思路如下: 利用自动化爬虫工具 Selenium 模拟点击输入等操作来进行登录 分析页面,获取点触验证码的点触图片,通过将图片发送给超级鹰打码平台识别后获取坐标信息 根据超级鹰返回的数据,模拟坐标 ...

  8. myblogplus 第三期 如何更改你博客的图标,已实现 - mooling原创

    三言两语 博客的logo可以凸显你的blog的个性 不知道你有没有觉得博客园原始的那个小矿工不好看了呢 fromto 这才是个人博客的style! 为什么要写这篇文章 因为在博客园的“找找看”中,如果 ...

  9. Unity代码混淆

    https://www.zhihu.com/question/25414422 http://blog.csdn.net/kun1234567/article/details/7917847 http ...

  10. EasyPoi导出Excel

    这几天一直在忙工作中的事情,在工作中有一个问题,可能是因为刚开始接触这个EasyPoi,对其也没有太多的理解,在项目中就使用了,有一个需求,是要导出项目中所有的表格,今天就对这个需求进行分析和实现吧; ...