彻底理解js中this
彻底理解js中this的指向,不必硬背。
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题。
为什么要学习this?如果你学过函数式编程,面向对象编程,那你肯定知道干什么用的,如果你没有学过,那么暂时可以不用看这篇文章,当然如果你有兴趣也可以看看,毕竟这是js中必须要掌握的东西。
例子1:
function a(){var user = "追梦子";console.log(this.user); //undefinedconsole.log(this); //Window } a();
按照我们上面说的this最终指向的是调用它的对象,这里的函数a实际是被Window对象所点出来的,下面的代码就可以证明。
function a(){var user = "追梦子";console.log(this.user); //undefinedconsole.log(this); //Window } window.a();
和上面代码一样吧,其实alert也是window的一个属性,也是window点出来的。
例子2:
var o = {user:"追梦子",fn:function(){console.log(this.user); //追梦子 } } o.fn();
这里的this指向的是对象o,因为你调用这个fn是通过o.fn()执行的,那自然指向就是对象o,这里再次强调一点,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个。
其实例子1和例子2说的并不够准确,下面这个例子就可以推翻上面的理论。
如果要彻底的搞懂this必须看接下来的几个例子
本文出处:追梦子博客
例子3:
var o = {user:"追梦子",fn:function(){console.log(this.user); //追梦子 } } window.o.fn();
这段代码和上面的那段代码几乎是一样的,但是这里的this为什么不是指向window,如果按照上面的理论,最终this指向的是调用它的对象,这里先说个而外话,window是js中的全局对象,我们创建的变量实际上是给window添加属性,所以这里可以用window点o对象。
这里先不解释为什么上面的那段代码this为什么没有指向window,我们再来看一段代码。
var o = {a:10,b:{a:12,fn:function(){console.log(this.a); //12 }} } o.b.fn();
这里同样也是对象o点出来的,但是同样this并没有执行它,那你肯定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不准确,接下来我将补充一句话,我相信你就可以彻底的理解this的指向的问题。
情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。
情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,例子3可以证明,如果不相信,那么接下来我们继续看几个例子。
var o = {a:10,b:{// a:12,fn:function(){console.log(this.a); //undefined }} } o.b.fn();
尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。
还有一种比较特殊的情况,例子4:
var o = {a:10,b:{a:12,fn:function(){console.log(this.a); //undefinedconsole.log(this); //window }} } var j = o.b.fn; j();
这里this指向的是window,是不是有些蒙了?其实是因为你没有理解一句话,这句话同样至关重要。
this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window,这和例子3是不一样的,例子3是直接执行了fn。
this讲来讲去其实就是那么一回事,只不过在不同的情况下指向的会有些不同,上面的总结每个地方都有些小错误,也不能说是错误,而是在不同环境下情况就会有不同,所以我也没有办法一次解释清楚,只能你慢慢地的去体会。
构造函数版this:
function Fn(){this.user = "追梦子"; } var a = new Fn(); console.log(a.user); //追梦子
这里之所以对象a可以点出函数Fn里面的user是因为new关键字可以改变this的指向,将这个this指向对象a,为什么我说a是对象,因为用了new关键字就是创建一个对象实例,理解这句话可以想想我们的例子3,我们这里用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a,那么为什么对象Fn中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。
除了上面的这些以外,我们还可以自行改变this的指向,关于自行改变this的指向请看JavaScript中call,apply,bind方法的总结这篇文章,详细的说明了我们如何手动更改this的指向。
更新一个小问题当this碰到return时
function fn() { this.user = '追梦子'; return {}; } var a = new fn; console.log(a.user); //undefined
再看一个
function fn() { this.user = '追梦子'; return function(){}; } var a = new fn; console.log(a.user); //undefined
再来
function fn() { this.user = '追梦子'; return 1; } var a = new fn; console.log(a.user); //追梦子
function fn() { this.user = '追梦子'; return undefined; } var a = new fn; console.log(a.user); //追梦子
什么意思呢?
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。
function fn() { this.user = '追梦子'; return undefined; } var a = new fn; console.log(a); //fn {user: "追梦子"}
还有一点就是虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。
function fn() { this.user = '追梦子'; return null; } var a = new fn; console.log(a.user); //追梦子
知识点补充:
1.在严格版中的默认的this不再是window,而是undefined。
2.new操作符会改变函数this的指向问题,虽然我们上面讲解过了,但是并没有深入的讨论这个问题,网上也很少说,所以在这里有必要说一下。
function fn(){this.num = 1; } var a = new fn(); console.log(a.num); //1
为什么this会指向a?首先new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。
相关文章:

cvsdfgdfdf
数组-136. 只出现一次的数字题目描述题目样例Java方法:位运算算法思路代码复杂度题目描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 题目样例 示例1: 输入: […

怎样操作vue.js使用3DES加密
如何在VUE-CLI手脚架建立的工程中使用3des加密: 1npm install crypto-js --save-dev1import CryptoJS from crypto-js123456789101112131415161718192021222324252627//DES加密 Pkcs7填充方式encryptByDES(message, key){const keyHex CryptoJS.enc.Utf8.parse(key…

PHP 函数 ignore_user_abort定时执行任务的实现
ignore_user_abort 设置与客户机断开是否会终止脚本的执行。本函数返回 user-abort 设置的之前的值(一个布尔值)。int ignore_user_abort ([ string $value ] )参数描述setting可选。如果设置为 true,则忽略与用户的断开,如果设置…

echarts树图节点垂直间距_矿棉板吊顶标准工艺节点
材料探秘materials材料版块【矿棉板吊顶标准工艺】 材料探秘关键词:#吊杆与设备#吊顶龙骨#矿棉板#1 吊杆与设备相遇增加过桥节点图 ■ 本工艺管控要点◎ 顶面的水、电、风专业强制定位、预留、预埋必须全部完成,且电气穿线、测试完成并合格…

队列 queue
STL: 队列中pop完成的不是取出最顶端的元素,而是取出最低端的元素.也就是说最初放入的元素能够最先被取出(这种行为被叫做FIFO:First In First Out,即先进先出). queue:front 是用来访问最底端数据的函数. 1 #include <queue>2 #include <cstdio>3 uisng namespace…

Android精通:View与ViewGroup,LinearLayout线性布局,RelativeLayout相对布局,ListView列表组件...
UI的描述 对于Android应用程序中,所有用户界面元素都是由View和ViewGroup对象构建的。View是绘制在屏幕上能与用户进行交互的一个对象。而对于ViewGroup来说,则是一个用于存放其他View和ViewGroup对象的布局容器! Android为我们提供了View和V…

redis删除过期key的算法_面试官别再问我Redis内存满了该怎么办了
概述Redis的文章,我之前写过一篇关于「Redis的缓存的三大问题」,累计阅读也快800了,对于还只有3k左右的粉丝量,能够达到这个阅读量,已经是比较难了。这说明那篇文章写的还过得去,收到很多人的阅读肯定&…

开源监控解决方案Nagios+Cacti+PNP4Nagios+NConf+NDOUtils+Nagvis(六)ndoutils安装
前面的文章已经说过,NDOUtils必须使用2.0的版本才支持nagios4x,比较幸运的是该版本2014年就已经发布。一.安装#tar -axf ndoutils-2.0.0.tar.gz -C /usr/local/src/#cd /usr/local/src/ndoutils-2.0.0#./configure --prefix/usr/local/nagios LDFLAGS-L/…

网络安全技术分析:DDoS的攻与防
根据墨者安全相关数据研究发现,从今年年初开始,DDoS功击的数量相比去年几乎是翻倍增长,特别是游戏、金融、政企、电商、医疗行业,更是DDoS功击的重灾区,很多企业是闻“D”色变。DDos(Distributed Denial of Service),中…

pcl求平面法向量_线性代数6——平面方程与矩阵
线性方程的几何意义二元线性方程该方程是一个二元线性方程组,包含两个方程,每个方程是一条直线,两条直线的交点就是该方程有唯一解,这就是二元线性方程的几何意义。平面方程空间内不在同一直线上的三点构成一个平面,平…

php 类中的各种拦截器
1、__get( $property ) 访问未定义的属性时调用class lanjie {function __get($name){echo $name." property not found! ";} }$ob new lanjie(); echo $ob->g; 当我们调用对象$ob未定义的属性g时,调用拦截器__get()方法,输出“g property…

[Vue CLI 3] 源码之 webpack-chain
我们看一下 webpack-chain 到底做什么? Use a chaining API to generate and simplify the modification of Webpack version 2-4 configurations.熟悉 cli-plugin-babel、cli-plugin-eslint 源码的话,你会时常看到它。 如何使用呢? 1、加载它 const Co…

openstack页面自定义插件使用详解(django、ajax、post)(zTree为例)
2019独角兽企业重金招聘Python工程师标准>>> 感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正! 如有转载,请保留源作者博客信息。 Better Me的博客…

lazyload.js实现图片异步延迟加载
所谓图片异步加载,意思是不用一次把图片全部加载完,你可以叫它延迟加载,缓冲加载都行。 看看你有没有这种需求:某篇文章图片很多,如果在载入文章时就载入所有图片,无疑会延缓载入速度,让用户等…

postfilter中文什么意思_Filterpost请求中文字符编码的过滤器 --学习笔记
java代码:import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class Lo…

错误:You can't specify target table 'xxx' for update in FROM clause的解决
今天在MySQL数据库删除重复数据的时候遇到了一个问题。如下脚本: DELETE FROM tempA WHERE tid IN ( SELECT MAX(tid) AS tid FROM tempA GROUP BY name,age ) 会出现报错信息: You cant specify target table tempA for update in FROM clause 大致意思…

HTTPS的七个神话(译文)
原文网址:http://blog.httpwatch.com/2011/01/28/top-7-myths-about-https/ 译文地址:http://www.ruanyifeng.com/blog/2011/02/seven_myths_about_https.html 误解七:HTTPS无法缓存 许多人以为,出于安全考虑,浏览器不…

蓝牙写入数据库_蓝牙 数据写入 简单易懂版(适合没写过蓝牙的看)
//字符串转arrbufferfunction string2buffer(str) {// 首先将字符串转为16进制let val ""for (let i 0; i < str.length; i) {if (val ) {val str.charCodeAt(i).toString(16)} else {val , str.charCodeAt(i).toString(16)}}// 将16进制转化为ArrayBufferr…

Educational Codeforces Round 9 F. Magic Matrix 最小生成树
F. Magic Matrix题目连接: http://www.codeforces.com/contest/632/problem/F Description Youre given a matrix A of size n n. Lets call the matrix with nonnegative elements magic if it is symmetric (so aij aji), aii 0 and aij ≤ max(aik, …

【SqlServer】SqlServer中的更新锁(UPDLOCK)
UPDLOCK.UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。当我们用UPDLOCK来读取记录时可以对取到的记录加上更新锁,从而加上锁的记录在其它的线程中是不能更改的只能…

Oracle CDC (Change Data Capture)更新数据捕获——概述
Change Data Capture能高效识别并捕获数据的插入、修改和删除,使更新数据供个人或应用使用。 CDC从oracle 9i开始引入,//TODO 在11G R2之后的版本里将取消支持,被Oracle GoldenGate取代。 CDC的一些概念 CDC有同步和异步两种模式,…

flutter ios启动白屏_Flutter技术架构概览
前言最近在整理各种技术架构,给自己的列了个TODO list,希望能在几个月的时间内,研究完各种前端技术架构,包括移动端技术架构。今天分享一下自己整理的flutter技术架构。完整的技术架构TODO list可以去我的github仓库查看ÿ…

SQL Relay开源的数据库池连接代理服务器
一、SQL Relay是什么? SQL Relay是一个开源的数据库池连接代理服务器 二、SQL Relay支持哪些数据库?* Oracle* MySQL* mSQL* PostgreSQL* Sybase* MS SQL Server* IBM DB2* Interbase* Sybase* SQLite* Lago* ODBC* MS Access三、安装和配置;…

关于Android开源库分享平台,(GitClub)微信小程序的开发体验
七八月份的深圳一直在下雨,总有人说雨天适合窝在家看书,对于程序开发者来说更是难得的学习机会。我们502工作室的小伙伴利用这个时间学习了一下微信小程序开发,并上线了一个GitClub小程序,目前功能有些简陋,难免有辣眼…

RSync实现文件备份同步
rsync是类unix系统下的数据镜像备份工具,从软件的命名上就可以看出来了——remote sync。它的特性如下:1、可以镜像保存整个目录树和文件系统。2、可以很容易做到保持原来文件的权限、时间、软硬链接等等。3、无须特殊权限即可安装。4、优化的流程&#…
Hibernate annotation多对多配置
角色(用户组),用户多对多。 角色实体配置: private Set<TAuthUser> users;ManyToManyJoinTable(name"t_auth_user_role",joinColumns{JoinColumn(name"role_id")},inverseJoinColumns{JoinColumn(name&…

ajax中的url如何传递变量_如何创建和参数化UDT数据类型中的变量及IN,OUT 等参数?...
从数据类型的意义上说 UDT 并不被 CPU 所识别,而是在离线程序中自定义(组合)的数据类型。 S7 程序的自定义数据类型并不能装载到 S7 CPU 中。UDT 是由递增的编辑器创建并编辑或由源文件的编译而生成。 当在块调用中进行变量传递时是不能将 UDT 作为内存地址区域来传…

[雪峰磁针石博客]kotlin书籍汇总
2019独角兽企业重金招聘Python工程师标准>>> 下载地址 Learning Kotlin by Building Android Applications - 2018 初级 Develop amazing applications that will help you understand and explore the fundamentals of Kotlin while covering 3 various types of p…

web集群时session同步的3种方法
web集群时session同步的3种方法在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,一个登录用户,一会是登录状…

属于python文件的操作有_Python的文件操作
1、初始文件操作1、使用python读写文件使用open()函数获取文件句柄,就可以操作文件了,根据打开方式不同能执行的操作也不同。打开方式有:r、w、a、r、w、a、rb、wb、ab、rb、wb、ab,默认用的是r模式2、只读操作(r、rb)2.1、只读模…