this是什么
this是一个指针,并且永远指向一个对象,对于非箭头函数来说
,具体指向哪个对象是在运行时基于函数的执行环境动态绑定的。对于箭头函数来说
,具体指向哪个对象是在箭头函数申明时的环境确定的。
this的使用场景--非箭头函数
this
的常用使用场景无非就是下面几种
- 作为对象的方法调用
- 作为普通函数调用
- 作为构造函数调用
- 作为事件的回调函数调用
- Function.prototype.call和Function.prototype.apply调用
1 作为对象的方法调用
例子
以上代码运行之后输出 longhanghang
结论
当函数作为对象方法被调用时,this指向该对象。
衍生
如果把对象里面的函数赋值给一个用var
定义的全局变量,然后再在全局下面执行会产生什么样的火花呢?
以上代码运行之后输出 wenyaoyao
刨析:因为此时getNameFun是在全局作用域下面执行的,所以this指向window。
2 作为普通函数调用
例子
以上代码运行之后输出 wenyaoyao
结论
当函数直接被调用时this指向全局对象,游览器里面是window
,nodejs里面是global
。
衍生
1 全局环境下使用var关键字定义的变量会直接挂靠到window上,如果是使用let和const呢?
以上代码运行之后输出 undefined
刨析: 可以发现let和const定义的变量并不会挂靠在window上,然后此时this指向的是window,所以打印的时候输出undefined。
3 作为构造函数调用
例子
以上代码运行后输出longhanghang
结论
当使用new运算符调用函数时总是会返回一个对象,this指向这个对象。这也就是大名鼎鼎的构造函数。
衍生
1 函数内部怎么区分一个函数的调用类型呢?
以上代码运行后依次输出 输出其他方式调用
,构造函数调用
刨析: 我们可以巧妙的在函数内部使用instanceof
对函数的调用方式进行判断。
4 作为事件的回调函数使用
例子
以上代码运行后输出 <div id = "test">点击我</div>
结论
作为事件的回调函数调用时,this指向绑定事件的dom对象。
衍生
如果在事件的回调函数里面咱们再定义一个函数,函数内部的this又会指向哪里呢?
以上代码运行后输出 window
刨析:此时的text是作为普通函数被调用的,所以指向windw。
5. Function.prototype.call和Function.prototype.apply调用
1 Function.prototype.call
1 Function.prototype.apply
以上代码最终输出都为longhanghang wenyaoyao 11
结论
执行一个函数我们通常都是采用的后面加()
的方式,例如有名为 getName
这样的一个函数,我们通常会 使用getName()
进行调用,这样调用的方式this
的指向会遵循我们前面说的四种情况,但是如果我们不这样调用,而使用call
和apply
方法来调用时,那么this
的指向取决于我们传的第一个参数,正如上面的示例,第一个参数我们传递的obj
,那么函数内部的this指向的就是这个obj
,后面的参数是函数执行时需要的参数,apply
方法跟call
方法作用差不多,只是后面的函数参数形式不同。
衍生
如果我们将函数作为对象的方法调用,然后再使用call
或者apply
时,会擦出怎么样的火花呢?
以上代码输出为wenyaoyao
刨析:当我们使用了call
或者apply
执行函数时,优先级会高于作为对象的方法调用
this的使用场景--箭头函数
1 作为对象的方法调用
例子
以上代码运行之后输出 wenyaoyao
。
结论
this
指向被申明时的环境,因为getName
被申明时实在全局环境下的,所以这里的this
指向window
。
衍生1
如果把对象里面的函数赋值给一个用var
定义的全局变量,然后再在全局下面执行会产生什么样的火花呢?
以上代码运行之后输出 wenyaoyao
刨析:当箭头函数被申明
的时候,this
指向的是window
。
衍生2
如果箭头函数里面嵌套一个箭头函数呢?
以上代码输出结果为wenyaoyao
刨析:当getFirstName
申明的时候是在getName
的这个作用域里面,this指向的就是getName
指向的this
,而getName
在申明的时候this
指向的是window
,所以结论就是getName
种的this
也是指向window
。
2 作为普通方法调用
例子
以上代码输出的结果是window
结论
this
指向被申明时的环境,因为getName
被申明时实在全局环境下的,所以这里的this
指向window
。
3 作为构造函数调用
例子
以上代码会报错 Uncaught TypeError: getName is not a constructor
结论
箭头函数不能作为构造函数调用。
4 作为事件的回调函数调用
例子
以上代码输出为window
结论
this
指向被申明时的环境,因为回调函数在申明时的环境是window,所以this指向window
。
5. Function.prototype.call和Function.prototype.apply调用
例子
以上代码输出为 window
结论
Function.prototype.call和Function.prototype.apply无法改变箭头函数this
的指向,this
的指向还是在申明时就决定了。因为申明时的环境时window
,所以this
指向window
而并不是指向构造函数Object
。
箭头函数和非箭头函数的区别
- 箭头函数长得帅,非箭头函数长得漂亮
- 箭头函数都是匿名函数,非箭头函数可以是匿名函数也可以是具名函数
- 箭头函数不能使用
new
关键字,非箭头函数可以 - 箭头函数没有
prototype
属性,非箭头函数有 - 箭头函数不绑定
arguments
,非箭头函数要绑定 - 箭头函数无法使用
call
和apply
修改的this
的指向,非箭头函数可以 - 箭头函数的
this
在申明时决定,非箭头函数的this
在执行时确定
自己实现call,apply,bind
前面用了这么多call和apply,那么咱们来点干货,自己手写一下这几个函数
1 call
最终输出的是obj
对象和11
2 apply
bind
bind
和call
以及apply
有一点区别就是函数调用bind
后会返回一个新的this
指向的函数,而使用call
和apply
是改成this
指向并执行
以上代码最终输出 {} 11 22 33
总结
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!