有很长一段时间没有更新博客了,近一段时间开始重新梳理知识点和写博客了,新的博客地址:欢迎访问。

在面向对象的语言中(例如Java,C#等),this 含义是明确且具体的,即指向当前对象。一般在编译期绑定。
然而js中this 是在运行期进行绑定的,这是js中this 关键字具备多重含义的本质原因。下面就让我们一起来分析一下具体情况。
由于js中this 是在运行期进行绑定的,所以js中的 this 可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。JavaScript 中函数的调用有以下几种方式:

  • 作为对象方法调用
  • 作为函数调用
  • 作为构造函数调用
  • 使用 apply 或 call 调用

JavaScript this决策树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3qCjhkBe-1570673274706)(https://img-blog.csdn.net/20160502194439159)]
根据这个决策树我们需要进行两步判断:
1.函数调用是用new进行调用的吗?如果是,则this指向新创建的对象,否则,进入"否"分支;
2.判断该函数是否是用dot(.)进行调用的,如果是,则即进入"是"分支,即this指向dot(.)之前的对象;否则this指向全局对象window.
demo1:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body><script type="text/javascript">function test(a){this.a = a;//相当于window.a}test(3);//这里相当于window.test(3)//所以test函数中的this指向了windowconsole.log(a);//3  这里相当于与访问window.a</script>
</body>
</html>

demo2:
对于say方法中的sayA和sayB中的this来说:不是通过new操作符来调用的,也没有通过dot(.)来调用,因此this指向window

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body>
<script type="text/javascript">var obj = {a:0,b:0,say:function(a,b){var sayA = function(a){console.log(this);//Windowthis.a = a;};var sayB = function(b){console.log(this);//Windowthis.b = b;};sayA(a);sayB(b);}}obj.say(1,1);console.log(obj.a+"--"+obj.b);//0--0console.log(window.a+"-----"+window.b);//1-----1
</script>
</body>
</html>

demo3:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>面试题</title>
</head>
<body>
<script type="text/javascript">function Person(name,age){this.name = name;this.age = age;}var person1 = new Person("lisi",18);console.log(person1.name);//lisivar person2 = Person("wangwu",12);//person2是undefined// console.log(person2.name);//Uncaught TypeError: Cannot read property 'name' of undefinedconsole.log(window.name);//wangwu//Person("wangwu",12)相当于window.Person("wangwu",12)
</script>
</body>
</html>

demo4:
apply 和 call 这两个方法切换函数执行的上下文环境(context),即可以改变this指向。obj1.say.call(obj2,3,3)实际上是obj2.say(3,3),所以say中的this就指向了obj2

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body>
<script type="text/javascript">function Test(a,b){this.a = a;this.b = b;this.say = function(a,b){this.a = a;this.b = b;}}var obj1 = new Test(1,1);var obj2 = {a:2,b:2};obj1.say.call(obj2,3,3);console.log(obj2.a+"--"+obj2.b);//3--3
</script>
</body>
</html>

demo5:
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象.当然这句话不完全准确,因为在不同环境下情况就会有不同。下面我们就来分析一下各种情况。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body>
<script type="text/javascript">// 这里的函数test实际是被Window对象调用的function test(){var name = "lisi";console.log(this.name);//undefinedconsole.log(this);//Window}test();//这里相当于window.test();
</script>
</body>
</html>

demo6:
如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
这个例子就是指向上一级对象obj

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body>
<script type="text/javascript">var obj = {name:"lisi",sayName:function(){console.log(this.name);//lisi}}obj.sayName();
</script>
</body>
</html>

demo7:
对象字面量obj={}
变量obj其实也是window对象的属性
所以可以这样来调用window.obj.sayName();
如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,这里this指向obj,而不是window

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body>
<script type="text/javascript">var name = "wangwu";var obj = {name:"lisi",sayName:function(){console.log(this.name);//lisi}}window.obj.sayName();
</script>
</body>
</html>

demo8:
如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body>
<script type="text/javascript">var obj = {name:"wangwu",objInner:{name:"lisi",sayName:function(){console.log(this.name);//lisi}}}obj.objInner.sayName();
</script>
</body>
</html>

demo9:
尽管对象objInner中没有属性name,这个this指向的也是对象objInner,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body>
<script type="text/javascript">var obj = {name:"wangwu",objInner:{// name:"lisi",sayName:function(){console.log(this.name);//undefined}}}obj.objInner.sayName();
</script>
</body>
</html>

demo10:
从这个例子我们可以看出:this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的
在这个例子中虽然函数sayName是被对象objInner所引用,但是在将sayName赋值给变量fn的时候并没有执行,所以this最终指向的是window对象。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>this指向</title>
</head>
<body>
<script type="text/javascript">var obj = {name:"wangwu",objInner:{name:"lisi",sayName:function(){console.log(this.name);//undefinedconsole.log(this);//Window}}}var fn = obj.objInner.sayName;fn();
</script>
</body>
</html>

demo11:
对象person可以点出构造函数中的name是因为new关键字可以改变this的指向,将这个this指向对象person.
这里new Person()创建了一个Person对象的实例,并赋值给了变量person

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>构造函数版this</title>
</head>
<body>
<script type="text/javascript">function Person(){this.name = "lisi";}var person = new Person();console.log(person.name);//lisi
</script>
</body>
</html>

demo12:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>当this碰到return</title>
</head>
<body><script type="text/javascript">/*如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例*/function fn2(){this.username = "lisi";return {};}var obj = new fn2;console.log(obj);//Object{}console.log(obj.username);//undefinedfunction fn1(){this.username = '王五';return function(){};}var b = new fn1;console.log(b);//function(){}console.log(b.username);//undefinedfunction fn(){this.username = '王五';return 1;// return undefined;}var a = new fn;console.log(a);//fn {username: "王五"}console.log(a.username); //王五//虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊function fn3(){this.username = '王五';return null;}var a = new fn;console.log(a);//fn {username: "王五"}console.log(a.username); //王五</script>
</body>
</html>

待续。。。

js中this指向学习总结相关推荐

  1. JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解

    前  言 学过程序语言的都知道,我们的程序语言进化是从"面向机器".到"面向过程".再到"面向对象"一步步的发展而来.类似于汇编语言这样的面 ...

  2. 绒毛动物探测器:通过TensorFlow.js中的迁移学习识别浏览器中的自定义对象

    目录 起点 MobileNet v1体系结构上的迁移学习 修改模型 训练新模式 运行物体识别 终点线 下一步是什么?我们可以检测到脸部吗? 下载TensorFlowJS-Examples-master ...

  3. 前端学习辑录(2):JS中this指向的问题

    目录 this指向的不同场景: 一.普通函数调用 二.定时器函数 三.构造函数调用 四.对象方法调用 五.原型对象调用 总结 this指向的不同场景: 一.普通函数调用 普通函数中的this是谁?== ...

  4. 关于js中this指向复习

    简单说this指向 谁调用指向谁 1.对象.方法() 中,方法中的this指向的就是对象 2.普通函数中的 this 指向window,这是因为 window 是JS中的顶级对象,可以通过window ...

  5. JS中this指向问题

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

  6. js中this指向问题总结

    1. 默认绑定规则 (1) 全局作用下 this指向window console.log(this); (2) 函数独立调用下 this指向window function test(){ consol ...

  7. js中this指向是什么以及指向谁

    首先window是浏览器中最大的对象,所有的对象都在window中,在使用时可以省略 全局环境中的this指向window对象 我们声明的变量,最后都会变成window对象的属性 我们声明的函数,最后 ...

  8. js 中location 的学习

    alert(location.hash);// 空 alert(location.host);//返回服务器名称和端口号 alert(location.hostname);//返回不带端口号的服务器名 ...

  9. 使用TensorFlow.js在浏览器中进行深度学习入门

    目录 设置TensorFlow.js 创建训练数据 检查点 定义神经网络模型 训练AI 测试结果 终点线 内存使用注意事项 下一步是什么?狗和披萨? 下载TensorFlowJS示例-6.1 MB T ...

  10. JavaScript学习笔记——JS中的变量复制、参数传递和作用域链

    今天在看书的过程中,又发现了自己目前对Javascript存在的一个知识模糊点:JS的作用域链,所以就通过查资料看书对作用域链相关的内容进行了学习.今天学习笔记主要有这样几个关键字:变量.参数传递.执 ...

最新文章

  1. hdu4847:Wow! Such Doge!(字符串匹配)
  2. 更改mssql数据库的名字
  3. Canvas动画基础之碰撞检测
  4. 虚机大比拼之HYPER-V
  5. MySQL5.6 Waiting for Commit Lock
  6. Java_Freemarker
  7. html的table效果,html的table用法(让网页的视觉效果显示出来)
  8. LeetCode84 Largest Rectangle in Histogram
  9. python中的模块_python3.0中重载模块
  10. HighCharts:饼图判断是否选中
  11. Codeforces Round #389 (Div. 2) 752E(二分答案)
  12. 拼多多淘宝虚拟店虚拟商品如何通过网盘发货机器人软件工具进行自动发货,怎么设置口令关键词?百度网盘自动发货机器人
  13. 凯利公式计算器安卓_华为MatePad Pro 5G评测:一屏双任务,打破安卓平板生态限制...
  14. 什么是可靠性测试,常见的可靠性测试标准有哪些?
  15. 江西交通职业技术学院计算机网课,第16章-桥墩计算_江西交通职业技术学院:桥涵工程(高职、精品课程)_ppt_大学课件预览_高等教育资讯网...
  16. 阿里云服务器租用费用清单表(CPU内存带宽磁盘)
  17. 【科普】准大一新生如何挑选笔记本电脑
  18. 技术在游戏研发中的重要性
  19. 计算机应用开班培训简报,信息技术提升培训简报及总结.doc
  20. IPv6 NDP——邻居发现协议

热门文章

  1. USB 3.0 高清音视频采集芯片——MS2130
  2. 指数增长模型matlab代码_多元思维模型1:复利模型——拥抱指数增长
  3. 跨考计算机 专硕还是学硕,考研我该如何抉择!专硕学硕不纠结
  4. 干货 | 携程用户数据采集与分析系统
  5. SPFA算法模板(刘汝佳版)--Wormholes POJ - 3259
  6. 特征值+SVD分解+伪逆(广义逆)
  7. uboot - 配置过程1(分析国产君正的ingenic-linux-kernel3.10.14-x1000-v8.2-20181116\u-boot\mkconfig脚本)
  8. QT 自定义类访问UI控件的几种方法
  9. 关于一个博客系统的 整体架构与技术
  10. Boost PFC参数计算——交流电的基本概念与推导