让人又爱又恨的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

时间: 2024-08-07 04:56:41

让人又爱又恨的this的相关文章

Java让人又爱又恨的“高端行业”

--动力节点java Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于个人PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥有全球最大的开发者专业社群.在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景. 在计算机应用以及遍及生活各个角落的时代,Java语言已经是使用最广泛的服务器端语言,覆盖到了关系国计民生的各个行业领域,如电信.银行.互联网等,这些行业的企业都在使用基于

position定位——让人又爱又恨的属性

关于css中的position这个属性,在使用的时候,有时很强大,有时又让人很无奈. 强大的时候,对于div中的一些小物件不方便使用margin或者padding的时候,给与position:absolute;再配备left.right.top和bottom,基本上就是想放哪里放哪里了. 让人无奈的时候,就是我们一旦滥用了position这个定位属性,就会让自己的布局飞的满天是,又因为z-index没有设定好,基本上,整体的布局就会让你手足无措,找原因的话,又非常麻烦,最后,恐怕只能推倒重做了.

为什么95后、00后这批消费者会让美业人又爱又恨?

刚刚摸清90后的消费喜好,95后.00后已经成为消费主体. 还没赚钱就已经很会花钱,95.00后的消费观让人头疼.这代人的出生伴随着数字化互联网的发展,比任何一代都熟悉电子产品和互联网的使用,使得他们的消费习惯和消费特征有了明确的变化.就连美容美发市场,95后,00后已经成为市场消费主力,如何吸引这部分高质量的消费者呢,那首先要对他们有深刻的了解. 近日,美媒发起一项针对年轻人的调查发现,中国的"Z一代"的年轻人的人生态度和生活方式明显与众不同.这些孩子生于2 0世纪90年代.21世纪

让人又爱又恨的char(字符型)

今天来总结一下char型,平常写算法的时候对这个东西感觉都有一点绕着走,说到底还是对这部分的知识不熟悉所以有点怕他,不过以后不要怕,今天来总结一下 首先,说到字符型数据类型,char型,恩它是一种数据类型 然后,就是字符型变量 字符型变量的重点是将一个字符存入字符变量中,实际上存入的不是这个字符的形,而是这个字符的ASCII码 输入:getchar(); 输出:putchar(); getchar和scanf的区别在于他可以输入空格 字符型常量: 1.普通 'a' 2.转义 1.‘\t’ 斜杠+

喜欢计算机的孩子们啊,欲望,将会是你又爱又恨的东西

我小学二年级接触数学竞赛,四五年级接触计算机竞赛,现在计算机系大三,关键这条路还是我自己选的,你肯定就知道我对数学和计算机感情多深了. 小学数学风生水起,到中学勉强双一保送,再到如今大学生活平平,身边人大都见证了我的颓废,而我自己觉得呢?颓废是颓废,可更准确地说,其实是迷茫. 数学好玩,我小时候一直这么觉得:数学没意思,计算机好玩,这是我中学的想法:如今,我觉得它们都好玩,只可惜自己走了弯路. 于是,愚蠢的我在奋斗的路上手忙脚乱.但正因我忙,我更想挤出时间把自己走的弯路记录下来,但愿后人别走我的

匹马行天下——没有无缘无故的爱和恨,没有无缘无故的编程

没有无缘无故的爱和恨,没有无缘无故的编程 前言: 想这世间,没有无缘无故的爱,也没有无缘无故的恨,一切都有有原因的,我想编程亦是如此,技术时常更新,程序员时常学习,随着时间的推移,程序员发际线的增高,生活无处不编程,未来必将是编程的天下,大势所趋,人工智能的时代已经到来,程序员还会少吗?敢问路在何方,路在脚下,人人心中的压力都是来自于自己不努力不积极而又不甘于现状,少给自己找借口,多给自己找方法,幸运女神不是人人都能遇到的,还是正确面对现实,我命由我不由天,人生赢在转折处,改变从现在开始. 一览

又爱又恨系列之枚举enum

其实枚举挺简单的,只不过以前没好好学,所以不知道这个东西,恩,现在梳理一下 整体而言,首先枚举是一个数据类型,这个数据类型和结构体有点像 可以分为三个层次 1.枚举数据类型定义 第一种:enum 枚举名 { 枚举元素 1, 枚举元素 2, ......, ...... } eg: enum week{Sun,Mon,Tue,Wed,Thu,Fri,Sat}; 2.枚举变量的定义 主要有两种方式 方式一:根据1中定义的数据类型定义枚举变量 enum week Workday,Holiday; 方式

择一人深爱,陪一人到老

有人说:爱上一座城,是因为城里住着某个人,能够与所爱的人在一起,连光阴都是美的. 即便粗茶淡饭,修篱种田,只要有你陪伴就好. 走过千山,曾经是一个人的浩浩荡荡,当生命的路口遇上了你的笑脸,岁月中有了两个人的地老天荒. 时光静好,与君语: 细水长流,与君同: 繁华落尽,与君老. 想来这一生,总会有一个人,牵着你的手,将爱融入生命,倾一世温柔,与你一起待霜染白发,陪你看细水长流. 择一人深爱,陪一人到老. 痴一人情深,留一世繁华. 爱是衣带渐宽终不悔的执着,爱是为伊消得人憔悴的不悔:爱是微笑向晚,携

从国考大数据看中国哪个省的人最爱当官

道路千万条,公务员之路最拥挤! 一个职位有成百上千人竞争的现象屡见不鲜 然而每年都有100多万勇士 敢于直面国考的惨烈 说起公考 全国那么多人 到底哪个省份的人最爱当官呢? 看数据分析就知道了 ▼ 先看下刚结束的2020年的国考大数据. 数据分析显示,2020年国考共招录24128人,有143.7万人通过资格审核,参考人数达96.5万人,竞争比高达40:1. 其中,2019年的这场国考,被称为"史上最难国考".经过2018年报考高峰后,2019年,国考突然大缩水,招考职位从2018年的