在初阶段我看js中的时候简直就是一脸蒙B,跟现在的棒子国的女人一样,看来看去都是一个样,但是根本上还是不知道出自那个医生之手。
看完我这篇文章解析之后,你再到大街上蹲点去看看那些girl脸,那些是true or false,为了证实你真的看懂的js的this,你再去问问那些girl我说的是对的麻,但我不保证你不被打死。
本文规定 //=> 后面指的都是输出的结果
我们在游览器上先打印出最简单的this.看看是什么鬼
我在浏览器里console.log(this) //打印出window{......} 打印出一个window对象
函数中执行时this的指向(1)最原始的函数调用
//=>window{.....} 此时输出的还是window对象,因为函数被调用的情况下为全局对象,所以this.指向的为window对象,
函数中执行时this的指向(2)最原始的函数调用 ‘use strict'
//=>undefined 此时输出了一个underfined,在严格模式下此时对this.不会指向全局,而是全指向一个underfined ,以避免在写代码时出现一些莫名的情况,本来js就是一个不严谨的语言
作为一个对象字面量的方法调用时this的指向
//=>"ziksang" 此时输出一个字符串ziksang 此时的this指向的是obj对象,此时调用的this是根据运行时找到this的指向 ,指向的是obj对象,而obj对象下面有一个name为ziksang的属性,所以运行时候打印出的就是ziksang
后面还要讲到一个定义时this指向的对象,所以我们一定要搞定运行时和定义时this的不同
彻底讲清this运行时指向的对象
//=>ziksang 根据前面的知识调用say()方法时我们一目了解的知道this.指向的是window对象,而window对象下面挂着一个name属性,所以调用this.name指向的是window下name的属性值,在这里我加了一个严格模式,如果不加'use strict',我不定义name属性则不会报错,因为变量提升的原因,加了之后 则会报一个
Uncaught TypeError: Cannot read property 'name' of undefined!!!意思说没有name这个属性 ,这些只是一个运行时指向的一个铺垫讲解,让我们去看看棒子mm到底怎么整成一个像一个娘养出来的
obj.say() //=> obj{} 此时obj.say()打印出来是一个obj对象,此时say方法里面的this.不是指向window对象麻 ?? 只是obj里面定义了一个say方法引用了say函数,说明一点此时say函数this是运行时才指向的, 指向了obj对象
obj2() //=>window{}对象 此时obj2()指向的是window对象 ,因为obj2是一个全局对象,挂在window下的,只是把obj.say对象的方法赋值给obj2变量,指行obj2() 指向的了window对象,这更说明了无论this定义时指向那里不是我们关心的,我们更关心,执行this时的运行环镜指向那里更为重要
再来一点恶心的东西,就是那些没牌没证的棒子医生,setTimeout里this的指向
理所当然的想法输出//=>ziksang
obj.say() //=> 有军魂 突然一看又是一脸蒙B 前面还好好的this.name指向obj里的name属性,为什么加一个settimeout就变了呢??还是要说到this运行时指向的对象,因为setTimeout是window对象的方法,你造也造不出来,你改也改不掉!那此时this.name运行时理所当然的就指向了window对向下的name属性,我在全局对象上挂了一个name属性"有军魂"!所以最后打印出有军魂
如何整治无证无牌上路的老司机,直接打掉黑作坊 用闭包改变this的指向
obj.say() //=> “ziksang” 我们改变了setTimeout运行时的指向,
在say方法里加一个局部作用域,把指向obj对象的this赋值给_this
,在setTimeout调用时直接改面其指向的window对向,硬改成obj对象,就能输出ziksang
宁愿被打脸也要说出事实,不向棒子妥协 ,别以为偷偷换脸就认不出你, this隐式改变
test() //=> undefined 前面讲过在严格模式下 ,原生的调用函数this不会指向window对象,而是打印出一个undefined。
为什么?为什么?setTimeout执行 //=>输出 window对象 , 你服不服,反正我心里是不服,不是被啪啪打脸,不服也不行,直接看原因吧,因为setTimeout里面执行的匿名函数会隐式改变其this的指向,指向window。这一点大家一定要记在心里,脸不能被白打,吃一堑长一智!
构造函数里的this
构造函数和普通函数有什么区别?构造函数用new去实例化一个对象 !普通函数则是直接调用
new Ziksang() //=>打印出来是Ziksang{name:"ziksang",__proto__:"object"} 如果用new 构造出来的函数this指向这个构造器的本身 constructor指向Ziksang,本质上来说this和constructor指的是同一个地方
Ziksang()用函数调用的话 就像我们前面说的一样指的是window对象,严格模式下指的是undefined;
ECAMscript6就像中国的整容医生,这抄一点那抄一点就是全球第一 ECAM6中的this 箭头函数
在这这里面你看出来什么!看出来什么 ?
我擦输出肯定是//=》有军魂
我莫名的感觉脸又肿了起来,前面还指向window对象下的this 就变了一个写法就又变了,
前面讲的是运行时的环境,但如果用了es6那就是定义时的环境了。
正确输出 //=》ziksang 因为用了箭头函数时 ,this指向的是定义时的对向,此时定义在obj对象里,虽然运行时指向的是window对象,但是只要使用箭头函数就会指向定义时指向的对象,所以这里输出了ziksang
装个B总结一下,打LOL去了
还有一个小细节当箭头函数运行时用call apply bind来改变其this指向也是TNN的不可能的,孩子别意想天开了,ES6就是想让Javascript的运行环境越来越规范,不要意想天开了孩子
写到这里我也累了,其实这个this还可以更深层次的讲,那就是用call apply bind来改变其this的指向,但作为我的想法就是一步一步来,之所谓深入了解,和解剖分析,就是让大家一步一步进入javascript的世界,真正知道javascript中的this改何去何从,实在憋不住LoL的诱惑了,你们谁改与我一战 黑色玫瑰 QQ494755899 外号ziksang SOLO我能把你打的回家深入了解this