JavaScript中箭头函数与普通函数到底有什么区别?
简单来说: 普通函数拥有自身的this,而箭头函数自身没有this
箭头函数表达式(箭头函数)的语法比函数表达式(普通函数)更简洁,并且箭头函数没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
我们先来看看普通函数和箭头函数的语法
COPY
1 | // 普通函数 |
没有单独的this
在箭头函数出现之前,每一个新函数根据它是如何被调用的来定义这个函数的this值:
- 如果该函数是一个构造函数,this指针指向一个新的对象
- 在严格模式下的函数调用下,this指向undefined
- 如果该函数是一个对象的方法,则它的this指针指向这个对象
我们来看看一段代码
COPY
1 | var name = '张三' |
实际上this是根据一个原则指向的:谁调用我,我就指向谁
当我们调用test('李四')
的时候其实是window.test('李四')
所有才会导致this指向全局的name
变量
我们在看一段代码,你可能就会明白了(这里我就不绕弯了,直接使用不同的变量名)
COPY
1 | var username = '李四' |
解析:其中有6个输出,下面我就以1-6的形式进行对号解析(文字有点多,耐心阅读)
首先说明以下,我们是通过obj来调用方法的(上面已经提到过,谁调用,this就指向谁),所有这里的this是指向obj对象的
- 调用方法时传入了一个
迪迦
的字符串,所有当我们输出uname的时候就会得到我们传入的迪迦
在obj里并没有uname所有才会输出undefined
- 开头已经说了,谁调用,指向谁,那为什么name会输出空字符串呢?
因为函数会向上查找内容直到window才会停止,如果window也没有的话则为undefined
(注意是在声明的地方向上查找,而不是调用的地方上查找),而window全局变量了是有一个name变量的并且内容为’’(空字符串)所有就找到了’’
第二个参数输出张山,原因是this指向obj的(obj调用了方法,所以this指向obj) - 输出
李四
因为当前方法内没有username变量,所以会向上查找,直到window
在obj里并没有username,所以输出undefined - setTimeout方法是属于全局方法,其实默认是省略掉了window(window.setTimeout())
第一个输出参数:为什么不输出迪迦,而是undefined?
这个问题就比较刁钻了,由于setTimeout方法是window方法(全局方法),那么在调用setTimeout方法的时候是window调用的(window.setTimeout())而setTimeout方法内定义了一个函数,并且需要一个函数为uname的参数,可并没有人传入这个方法传入任何内容,而方法内又要输出这个变量,所以它只能向上查找,可是window就是最后一层了,并且window并没有uname,所以输出undefined
第二个输出参数:全局变量并没有uname所以输出undefined - 为什么输出为两个’’(空字符串),原因很简单,setTimeout是window全局方法,如果setTimeout内没有通过var name = ‘hi’或者通过调用其他方法的返回值的话,window全局变量种有一个name变量为’’(空字符串),你可以打开所有网站,输入控制台输入
console.log(window)
window全局变量中的确又nameconsole.log(window.name)
或者console.log(name)
都会输出’’(空字符串) - 同第五个console.log的说法差不多,this指向window,并且会向上查询,所有会的到全局的username
把普通函数改为箭头函数
COPY
1 | var username = '李四' |
解析: 这次解析我就不写那么多文字了,你只需要记住一点,箭头函数没有this,所有它会向上查找,直到window才会停下,如果window没有就返回undefined(下面的解析,重复的话我就不说了)
注意:obj对象是没有this的,只有方法才会有this
- 输出传入的参数
迪迦
。同第四个解析 - 由于前面说过,window全部变量下有个name变量并且内容为’’空字符串
- 由于obj没有this,箭头函数也没有,所有输出全局变量username的内容
- 由于箭头函数没有this,所有它就会向上查找,obj也没有this,就找到了window,window没有就undefined
- 同第二个解析
- 同第三个解析
关于window全局变量为什么会有name变量的问题:https://blog.lete114.top/article/browser-window.name-property.html