导语
首先,如果搜索:js中this的指向问题
必然会得到这个结论:this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定,this最终指向调用它的对象。
但是发现有时候只依靠这句话还是会在判断this指向的时候出现问题。今天通过几个例子彻底搞懂this指向问题。
例子1
function flora(){ var Animal = "?"; console.log(this.Animal); //undefined console.log(this); //Window}flora();复制代码
实际上,这里调用flora();
是由window对象调用的,把flora();
改成window.flora();
控制台打印的同样是Window。
例子2
var flora = { Animal:"?", say:function(){ console.log(this.Animal); //? }}flora.say();复制代码
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定,这里flora
调用了say
,所以this指向对象flora
。
例子3-1
var flora = { Animal:"?", say:function(){ console.log(this.Animal); //? }}window.flora.say();复制代码
例子3-2
var flora = { Animal:"?", mars:{ Animal:"?", say:function(){ console.log(this.Animal); //? } }}flora.mars.say();复制代码
例子3-1的this竟然没有指向window
,例子3-2的this竟然没有指向flora
,不是说this最终指向调用他的对象吗?!! 结论竟然失效了,其实也不是,对于这种多层调用的情况
一个含有this的函数不管被多少花里胡哨的对象调用,this也只是指向它上一级的对象
例子4
var flora = { Animal:"?", mars:{ Animal:"?", say:function(){ console.log(this); //window console.log(this.Animal); //undefined } }}var pink = flora.mars.say;pink();复制代码
…fá生了什么,this怎么指向了window? 别急,想想我们的理论:this最终指向调用它的对象;
什么时候调用了它?是不是pink()
的时候,这个跟上面的?不一样,上面的例子直接执行了say
;
没有哪一句话可以让我们直接判断this指向,分析的时候小心一点就可以啦(⁎⁍̴̛ᴗ⁍̴̛⁎)
例子5-1
function flora(){ this.animal = "?";}var blue = new flora();console.log(blue.animal); //?复制代码
这里blue
对象之所以可以打印出函数flora
里面的animal
是因为new可以改变this的指向
其实可以这么理解,我们在var blue = new flora();
的时候,复制了一个flora
到blue
里面
注意⚠️这个时候并没有执行,而调用的时候是blue对象,所以this指向的就是blue
为什么blue
有animal
属性,因为flora
已经复制到了blue
对象中。
如果构造函数有返回值呢?⬇️
例子5-2
function flora(){ this.animal = "?"; return {}}var blue = new flora();console.log(blue.animal); //undefinedfunction flora(){ this.animal = "?"; return function(){};}var blue = new flora();console.log(blue.animal); //undefined复制代码
返回的是一个对象,this指向的就是那个返回的对象;
例子5-3
function flora(){ this.animal = "?"; return 1;}var blue = new flora();console.log(blue.animal); //?function flora(){ this.animal = "?"; return undefined;}var blue = new flora();console.log(blue.animal); //?复制代码
如果返回的不是对象,this还是指向这个函数的实例
例子5-4
function flora(){ this.animal = "?"; return null}var blue = new flora();console.log(blue.animal); //?复制代码
比较特别的是:虽然null
属于对象,但是返回null
依然指向函数实例
Null类型只有一个值的数据类型,这个特殊值是null。从逻辑角度来看,null值表示一个空对象指针,这也是使用typeof操作符检测null值时会返回"object"的原因
补充
- 箭头函数:箭头函数本身是没有this,但我们用到this的时候,他会找定义函数时所处环境的this.
- 在严格模式下,默认的this不是window,是undefined。(使用了"user strict"启用严格模式)
- new之所以可以改变this的指向,跟apply有关,还有其他方法可以改变this指向,后续文章会提到
给大家做两道测试题吧!?
测试题
测试题1
var animal = '?'; function flora() { var animal = '?'; console.log(this.animal); } window.flora(); var obj = { animal: '?', say: function() { console.log(this.animal); } } obj.say(); var mrz = obj.say; window. mrz();复制代码
答案:? ? ?
测试题2
var animal = '?'; (function() { var animal = '?'; console.log(this.animal); })() function flora() { var animal = '?'; function mrz() { console.log(this.animal); } mrz(); } flora();复制代码
答案:? ?
- 因为匿名函数没有名字,所以就挂给
window
- 谁调用
mrz
那么就指向谁,它不是window
调用的,也不是flora
调用的,没有人管它,那么它就指向window
,无主函数