让人又爱又恨的this
this是个神奇的东西,
既可以帮助我们把模拟的类实例化、
又可以在事件绑定里准确指向触发元素、
还可以帮助我们在对象方法中操作对象的其他属性或方法、
甚至可以在使用apply、call、bing、filter等方法时指向我们指定的对象,以便灵活的使用。
但是如此强力的东西,势必有时难以把握,今天遇到一问题,出了错,重新温故下常见的this指向问题。
要说灵活无比的this的指向,很有必要先知道一个知识点,JavaScript中有四种调用模式。
this的指向很大程度收调用模式的影响,具体如下
1.构造器调用模式=>this指向实例化出来的对象
2.方法调用模式=>this指向方法所属的对象
3.函数调用模式(即函数不是对象的方法,仅仅普通调用时,今天就错在这,5555)=>this指向全局对象global(在浏览器运行环境下,global其实就是window)
4.apply调用模式=>this指向apply方法接收的第一个参数
看文字或许不太明了,上点代码
//先来看看构造器调用模式和方法调用模式 var name='你查看的是全局对象的属性';
var Foo=function (name) {
this.name=name;
//这里的this是在构造函数里,当new+构造函数实例化对象时,this会被绑定到实例化的对象上
this.say=function () {
console.log(this.name);
// 这里或许会有误解,事实上此处的this并没有绑定到构造函数实例化的对象上!!
}
}
var foo=new Foo('我是构造函数实例化的对象');
//这里就是构造器调用模式,构造函数里的this就是此时绑定到实例化对象上的 foo.say();//打印:我是构造函数实例化的对象
//这里的调用就是方法调用模式,它的特点是,有一个.或者[]这样的属性提取操作 //下面我们来证明console里的this没有被绑定到实例化的对象上
var say1=foo.say;
say1();//打印:你查看的是全局对象的属性 //造成这样的原因在于,console所属于的函数被赋值给了this.say,但是并没有被调用,所以this的指向并没有决定。知道这很重要
//再来看看函数调用模式,此处代码接着上面的写 function foo2() {
console.log(this.name);
}
foo2();//打印:你查看的是全局对象的属性
//这就是函数调用模式 console.log(this.name);//打印:你查看的是全局对象的属性
//注意哈,当不在函数里时this也是指向全局对象 var obj1={
name:'我是对象obj1的属性',
say:function(){
console.log("1:"+this.name);
(function(){
console.log("2:"+this.name)
})();
//别被误导了哈,这里没有什么作用域链,紧记不是apply调用(即this指向没有被强制改变)、方法、构造器调用时,都是函数调用模式,this都指向全局对象!!
}
}
obj1.say();
//打印:1:我是对象obj1的属性-----此处this所在的函数是say,它是被obj1.say()用方法调用模式调用的
//打印:2:你查看的是全局对象的属性------此处的this所属的函数是一个立即执行的匿名函数,它不是被方法调用的,是函数调用模式,此时不管它属于哪个对象,只要它没有被bind等方法改变this指向,它里面的this一定指向全局对象
//最后来看看apply调用模式 var obj2={
name : '我是对象obj2的属性',
}
foo.say.apply(obj2);
//打印: 我是对象obj2的属性
//这就是apply调用模式,相似的还有
foo.say.call(obj2);
//打印: 我是对象obj2的属性 //两者的共同点,就是
//调用的函数里的this会指向apply/call的第一个参数 //至于两者的区别,主要是传递的其他参数不同,感兴趣的可以自己了解,百度谷歌都很多
其实还有其他改变this指向的方法,就是一开始题到的bind\filter等方法,
但其实都大同小异,本质都是改变this的指向,使其指向传入参数,和apply/call类似,就不多做阐述了
最后上一下今天做错的题
//代码很简单,就是一个构造函数,
//要求在waitAndShout方法被调用时,延迟调用shout方法 //刚开始我是这么写的,毫无疑问,这样错了
var Obj=function (msq) {
this.msq=msq;
this.shout=function () {
alert(this.msq);
}
this.waitAndShout=function () {
setTimeout(function () {
this.shout()//会在这里报错,not a function
},2000);
}
}
var obj=new Obj('ddd');
obj.waitAndShout() //这是为什么呢?
//如果你仔细看上面的代码,想必早已知道原因。
//没错,原因就是setTimeout所在的函数只是被赋值给waitAndShout,
//但并没有被调用,他里面的this也不会在构造函数被调用时,指向实例化的对象
//另一个关键是setTimeout里执行的函数是被函数调用模式调用的,所以这里的this是全局对象,而我们没有给window创建shout方法,当然也就不是个函数了 //那么要怎么解决这个问题呢,解决方法很简单
//用一个变量接收this
this.waitAndShout=function () {
var that=this;
//重点就在这里!注意看,这里的this所属的函数被赋值给了waitAndShout
//也就是说this所在的函数就是waitAndShout,当他被调用时
//obj.waitAndShout()很明显是方法调用,那this就指向了obj
//此时我们把这个对象的地址传给变量that,那that就一直指向这个对象了,
//延迟调用时就不涉及this的指向问题,不用担心setTimeout延迟执行是以函数调用模式,也就实现了目标。 setTimeout(function () {
that.shout()
},2000);
}
汗,本来只是想随便写写,温习下的,结果写那么多
表达能力还是需要锻炼啊,注释比代码多那么多
时间关系,这次暂时不精简注释了,以后多注意下,多写写,应该就能简短的注释说明问题了吧。0.0
让人又爱又恨的this的更多相关文章
- 谈谈Nancy中让人又爱又恨的Diagnostics【上篇】
前言 在Nancy中有个十分不错的功能-Diagnostics,可以说这个功能让人又爱又恨. 或许我们都做过下面这样的一些尝试: 记录某一个功能用到的相关技术信息 记录下网站的访问记录 全局配置某些框 ...
- Lambda-让人又爱又恨的“->"
写在前边 聊到Java8新特性,我们第一反应想到的肯定是Lambda表达式和函数式接口的出现.要说ta到底有没有在一定程度上"优化"了代码的简洁性呢?抑或是ta在一定程度上给程序员 ...
- 让人又爱又恨的Lombok,到底该不该用
1 简介 Lombok,印尼的一个岛屿,龙目岛.但在Java的世界里,它是一个方便的类库,能提供很多便利,因此得到许多人的青睐.但也有不少反对声音.这是为什么呢? 之前去龙目岛拍的日落. 2 Lomb ...
- 让人又爱又恨的char(字符型)
今天来总结一下char型,平常写算法的时候对这个东西感觉都有一点绕着走,说到底还是对这部分的知识不熟悉所以有点怕他,不过以后不要怕,今天来总结一下 首先,说到字符型数据类型,char型,恩它是一种数据 ...
- MySQL让人又爱又恨的多表查询
1. 前言 在SQL开发当中,多表联查是绝对绕不开的一种技能.同样的查询结果不同的写法其运行效率也是千差万别. 在实际开发当中,我见过(好像还写过~)不少又长又臭的查询SQL,数据量一上来查个十几分钟 ...
- 又爱又恨系列之枚举enum
其实枚举挺简单的,只不过以前没好好学,所以不知道这个东西,恩,现在梳理一下 整体而言,首先枚举是一个数据类型,这个数据类型和结构体有点像 可以分为三个层次 1.枚举数据类型定义 第一种:enum 枚举 ...
- 爱与恨的抉择:ASP.NET 5+EntityFramework 7
EF7 的纠缠 ASP.NET 5 的无助 忘不了你的好 一开始列出的这个博文大纲,让我想到了很久之前的一篇博文:恋爱虽易,相处不易:当EntityFramework爱上AutoMapper,只不过这 ...
- 搞不懂为什么开发人员爱iOS恨Android?
导读:很多网站发表文章大同小异.唯有这个不同点,给大家分享. Android和iOS的较量一直都是人们津津乐道的话题.两个平台各有各的优势所在,同时也都力图能在各个方面赶超对手.对于用户来说,青菜萝卜 ...
- 又爱又恨的BOOTSTRAP
搞本书,看了一天,确实,,UIKIT比它好用... 但,艺多不压身吧. 今天自己抄了个大概的,不用其它插件,,但那手风琴,真的找了很多,没有中意的... <!DOCTYPE html> & ...
随机推荐
- ZEN、ELECTRA、ALBERT
一.ZEN 目前,大多数中文预训练模型基本上沿用了英文模型的做法,聚焦于小颗粒度文本单元(字)的输入.然而,与英文相比,中文没有空格等明确的词语边界.这个特点使得很多文本表达中存在的交叉歧义也被带入了 ...
- 使用composer安装Larave提示“Changed current directory to C:/Users/Administrator/AppData/Roaming/Composer”
解决办法: 根据官方手册执行composer global require "laravel/installer" 显示Changed current directory to C ...
- Codeforces Round #599 (Div. 1) B. 0-1 MST 图论
D. 0-1 MST Ujan has a lot of useless stuff in his drawers, a considerable part of which are his math ...
- 一份完整的PyCharm图解教程
PyCharm 是一种 Python IDE,可以帮助程序员节约时间,提高生产效率.那么具体如何使用呢?本文从 PyCharm 安装到插件.外部工具.专业版功能等进行了一一介绍,希望能够帮助到大家. ...
- H5生成二维码
要用H5生成二维码: 1.引入js库,可自行点击链接复制使用 <script type="text/javascript" src="http://static.r ...
- IT兄弟连 Java语法教程 数据类型 进制转换
● 正十进制转换为二进制 拆分法,将十进制整数拆分为若干个二进制权重的和,若有该权重则下面写1,否则写0.如: 34 = 32 + 2 128 64 32 16 8 4 2 1 0 0 1 0 ...
- 详解JAVA8函数式接口{全}
1: 函数式接口 1.1 概念 1.2 格式 1.3@FunctionalInterface注解 1.4 调用自定义函数接口 2:函数式编程 2.1:lambda的延迟执行 2.2 使用Lambda作 ...
- 计算机组成原理——cache高速缓存存储器
转载自https://blog.csdn.net/chen1083376511/article/details/8187481 cache-高速缓存存储器 在主存与CPU之间插入一级或多级SRAM组成 ...
- 【分布式架构】--- 基于Redis组件的特性,实现一个分布式限流
分布式---基于Redis进行接口IP限流 场景 为了防止我们的接口被人恶意访问,比如有人通过JMeter工具频繁访问我们的接口,导致接口响应变慢甚至崩溃,所以我们需要对一些特定的接口进行IP限流,即 ...
- UI设计中,文本底部添加下换线
最近在开发项目,针对小程序前端,显示文本需要添加下划线问题,起初是通过border-bottom:1rpx solid #eee; 进行编写,但是总是觉得线的高度过于粗,移动端最小单位值是 1 即: ...