导语
首先,如果搜索: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); //undefined
function 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
,无主函数