我这么跟你解释后,你还搞不this怎么指的,你找我...

在JavaScript中,this的意思为“这个;当前”,是一个指针型变量,它动态指向当前函数的运行环境。在不同的场景中调用同一个函数,this的指向也可能会发生变化,但是它永远指向其所在函数的真实调用者;如果没有调用者,就指向全局对象window。
上面这段话只要记住一句:它永远指向其所在函数的真实调用者
那么我们来分析一下什么是真正的调用者,如下
function a() {
console.log(this)
}
a()
我们学过执行上下文与作用域都明白一个点,这样定义的函数或者变量都会默认绑定到window上面去,那么上面那种调用还有一种方式就是,如下
function a() {
console.log(this)
}
window.a()
同时两种函数执行后的打印结果,this都是指向window
接下来,我们再看一种情况。首先我们想象一下this一般在哪用的最多? 答案肯定是对象里面 所以我们来看一下 对象里面的this指向
var name = '大罗'
let obj = {
name:'小罗',
fn:function(){
console.log(this.name) // name是谁?
}
}
obj.fn()
引用刚才我们说的:它永远指向其所在函数的真实调用者
我们怎么找到真实调用者这才是关键,很简单。我们看一下函数前面是谁呀。 fn函数前面是不是obj? 那么obj就是这个真实调用者
所以推断出obj == this是调用者,那么把函数里面this从脑海里面做一下隐式替换 不就相当于如下
var name = '大罗'
let obj = {
name:'小罗',
fn:function(){
console.log(obj.name) // 隐式替换
console.log(this.name) // name是小罗
}
}
obj.fn()
接下来我们再看一种情况,咱们把函数从对象上面提出来,如下
var name = '大罗'
function fn1(){
console.log(this.name) // name是谁?
}
let obj = {
name:'小罗',
fn:function(){
fn1()
}
}
obj.fn()
直接告诉大家结果,这里的this.name打印出来是大罗。 此时伙伴们就要问了,刚才还说最终调用者是看函数前面的东西。现在函数前面的东西没变。怎么结果就变了呢?
首先我们不要陷入思维误区,观察事情一定要仔细。
我们来看obj.fn()是一个定义好的函数。然后函数里面fn1()是一个函数调用哦,就是咱一开始就提取出去的函数嘛。。对吗?
那么看obj.fn()函数体里面的fn1()前面有东西调用它吗? 显然是没有,那么咱又回到一开始说的,如果函数前面没有东西调用,是不是默认就是window在调? 完整写法window.fn1() 如下
var name = '大罗'
function fn1(){
console.log(this.name) // name是谁?
}
let obj = {
name:'小罗',
fn:function(){
window.fn1() //fn1()前面不加调用者,默认就是window
}
}
obj.fn()
那这一切的一切就顺理成章的串起来,函数前面调用者是谁,this就指向谁。函数前面如果没有调用者,默认就指向window
好了想必大家心里都有一个底了。咱们直接上几道面试题,然后套用一下刚才的思想
1.第一道
const object = {
message: 'Hello, World!',
getMessage() {
const message = 'Hello, Earth!';
return this.message;
}
};
console.log(object.getMessage()); // => ?
分析:啥都不说了,直接看函数前面是谁,最后结果就是谁。 打印出来肯定是:Hello, World!
2.第二道
var name = 'Bell'
function Pet(name) {
this.name = name;
this.getName = function a(){
return this.name;
}
}
const cat = new Pet('Fluffy');
console.log(cat.getName()); // => ?
const { getName } = cat;
console.log(getName()); // =>?
分析:啥都不说了,直接看函数前面是谁,最后结果就是谁。第一个函数后面是cat,那么打印出来就是创建实例的时候传进去的值:“Fluffy”。 第二个函数前面什么都没有,那就默认window 打印出来就是 “Bell”
3.第三道
const object = {
message: 'Hello, World!',
logMessage() {
console.log(this.message); // => ?
}
};
setTimeout(object.logMessage, 1000);
分析:打印出来是undefined,首先我们要搞清楚这里object.logMessage只是取到了函数体,并没有真正的执行。执行一个函数后面一定是有双括号的。那么这里就相当于把函数体复制过来了,前面有东西调用它吗?显然没有,没有就是window调。 而此时window上面找不到message 那就是undefined呗
好接下来咱扩展一下。怎么让上面的函数打印出'Hello, World!'呢? 伙伴们思考30秒
刚才咱不是说了么。谁在函数前面,谁就是真实调用者。只要想办法让object在函数前面就行了,如下改造一下
const object = {
message: 'Hello, World!',
logMessage() {
console.log(this.message); // => ?
}
};
setTimeout(function(){
object.logMessage() //给它包一层函数,然后在这个函数里面直接调用logMessage函数
}, 1000);
除了上面的方法,还可以通过 bind 强行改变this指向
const object = {
message: 'Hello, World!',
logMessage() {
console.log(this.message); // => ?
}
};
setTimeout(object.logMessage.bind(object), 1000);
关于bind,call,apply的介绍以及用法,伙伴们可以去参考其他博客,这里就不多赘述了。
好了文章写到这里我的分享就结束了。。大家对this有新的认知了吗? 评论区告诉我
转载自:https://juejin.cn/post/7234059013271715897