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