You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
o()在非严格模式下打印输出window,因为此时变量o引用obj1对象的fn属性所指向的函数,即此时o和obj1.fn都只是指向存在堆内部的函数的引用,所以,此时直接o()相当于window.o()即window在调用堆中的函数,所以函数内打印的this是window。这里的var o = obj1.fn其实并不是保存obj1对象!!!而是告诉o,你可以跟我的fn属性引用同一个函数,但咱两不一样。
怕!(认真脸)
一开始想自己写关于this总结的,奈何自己水平有限,写出来也不够全面系统,所以这里为了this单独开一个
issue
,用于收罗我所遇到的关于讲解this较好的文章,最好做到由浅入深,如果有看客能看到并有更好的资源,请在评论里贴出来,让我加进来,哈哈哈哈哈,大家互帮互助嘛~真的明白了吗?巩固下!
例1:
能分别解释吗?
我尝试下:
obj1.fn();
打印输出obj1这个对象,因为此时fn
被obj1
对象调用,所以this指向obj1!o()
在非严格模式下打印输出window
,因为此时变量o引用obj1
对象的fn
属性所指向的函数,即此时o和obj1.fn
都只是指向存在堆内部的函数的引用,所以,此时直接o()
相当于window.o()即window在调用堆中的函数,所以函数内打印的this
是window。这里的var o = obj1.fn其实并不是保存obj1
对象!!!而是告诉o,你可以跟我的fn
属性引用同一个函数,但咱两不一样。例2:
例2为什么是window呢?
老实说,我以前也一直不知道为什么,只会死记硬背,知道我看了深入浅出 JavaScript 关键词 -- this一文,文中重点加粗的强调:
词法作用域?什么鬼???
一开始我也懵逼的,但是我依稀记得好像看过那么一丢丢《你不知道的js》,书上就有,我还写过一篇博客来记录,可惜当时菜,其实没怎么懂,接下去的内容又没去看,所以记忆不深,怪自己!
词法作用域在你在写代码时将变量写在哪里来决定的,而不是当执行时才确定! 一定要记牢这句话!!!
也就是说,当我们此时
obj2.fn()
时,我们以为它和例1一样,但由于内部fn
函数时箭头函数,所以跟我们原先的理解完全不同了。该箭头函数其实在定义好obj2
对象时就确定了它的词法作用域!它的词法作用域是什么?
这里,必须牢记,js里面没有块级作用域,只有全局作用域和函数作用域(
with
和eval
不提)。那么,当我定义obj2
时,箭头函数的词法作用域是谁?全局作用域!所以,这里打印输出this为window。
有人会说es6的
let
声明能形成块级作用域,如果上例用let
来声明会不会表现的不同呢?我来试试:即使换成
let
声明,结果依然不变!例3:
如果把它放进函数里面呢?试试:
这里
obj2
明明已经放进函数test
里面了啊,它的词法作用域应该就是test
函数作用域啊,那么为何打印输出依然是window呢?其实,这里等价于
function test() {console.log(this)}
!为什么这么说?因为此时我们都知道箭头函数词法作用域是test
的函数作用域,而该函数作用域的this
是什么?当然是看它被谁调用了啊!这里是window调用的它!例4(与例3对比):
明白了吗?不明白看个对比可能更好点:
这里的箭头函数的词法作用域是
fn
所指向的函数的作用域,那么只要看谁调用fn
谁就是this。例5
箭头函数告一段落,继续回到正常的函数中,看看闭包中的
this
这里为什么是undefined呢?
注意,这里可不是箭头函数了!其实这里等价于
var fn = f.fn(); fn();
这样一拆分,是不是很好理解了呢?例6:
why???
这里估计得先了解下
map
函数的实现才能很好理解,我先前贴出的链接里面有讲解,仔细看的肯定会知道原因。其实map里面的匿名函数是作为参数传递进去的,然后在map内部直接执行没有其他变量去调用它,所以在非严格模式下自然就是window了。
例7
看一个正常函数的闭包变异案例:
注意,这里不是箭头函数,不用考虑词法作用域!只需要看谁调用它即可。此例中直接在函数内部执行了
doIt()
,没有谁调用它。所以doIt
内部的this在非严格模式下指向window,而window内没有foo
属性,所以是undefined!例8
我想,上例第二个打印10应该都能理解了,但是可能会在
obj.c
打印40这里容易懵逼。上例中c
是obj
的属性,但是它并没有引用一个函数,当普通函数被调用时,this指向调用该普通函数的对象,但是如果调用的不是普通函数,那么情况就和箭头函数一样了,此时this应该由词法作用域确定!牢记上面这段话,回到例子中来,
obj.c
指向的并不是普通函数,所以在它被写下来时就已经确定了它的词法作用域是全局作用域,所以this是window,this.a + 20
等价于window.a + 20
。例9
擦擦擦,又犯错误了!!!
这里想错了,
fn
是普通函数,应该看它被谁调用!这里其实是arr
在调用!!!注意,不能对 this 直接赋值!例如:this = null,会报左边赋值无效!
总结
this是js的一个难点,有很多人凭工作经验去理解它,一般情况下他可能不会踩什么大坑,但一旦出现出现经验无法解决的坑,就很捉急了,所以建议在有一段开发经验后不要忘了去看一下深入基础的知识,好好巩固,把基础打牢,才能建高楼大厦!
The text was updated successfully, but these errors were encountered: