一篇文章带你看懂js函数指针this

函数的this指向问题一直都是困扰包括我在内的不少开发者的问题,我一直以来都是这样看待这个问题的,函数属于谁它的this就指向谁,直到我遇到了一个无法用这个简单粗暴的方法辨识的场景时,我才真正弄明白,函数的this并不一定指向占有这个函数的对象,而指向调用这个函数的对象,从现在起请牢牢记住这句话

函数的this并不一定指向占有这个函数的对象,而指向调用这个函数的对象

函数的this并不一定指向占有这个函数的对象,而指向调用这个函数的对象

函数的this并不一定指向占有这个函数的对象,而指向调用这个函数的对象

虽然结论很重要,不过这个结论并不是什么新鲜玩意儿,在有关js的书籍教程里面,都能找到这个结论,废话不多说,我通过源代码来推导这个结论,为了简化代码省略<script>标签

function test(){ console.warn('test', this) }; 
test();
//输出Window {0: Window, window: Window...

 控制台输出啥没人不知道吧,如果不知道建议去B站补超哥的视频,这里输出的是window,这里的test()等价于window.test(),在script里面声明的函数会自动变成全局的

//第一种写法等价于
var test = function(){ console.warn('test', this) }; 
test();

也就是变成window的成员函数,在这里有个直观的认识,test属于window,所以它输出的对象是window,但是记住这个结论是不对的

//上面两种写法等价于
window.test = function(){ console.warn('test', this) }; 
window.test();

为了阻止test提升为window的成员,我们使用es6的let/const来声明

let test = function(){ console.warn('test', this) };
window.test();
//window.test is not a function

问题来了,这里我们直接调用test()控制台输出的是谁?结果输出的还是window,所以直接推翻上面的说法,test不是window的成员却仍然指向window

let test = function(){ console.warn('test', this) };
test();
//输出Window {0: Window, window: Window...

 其实只到这里,这个结论就可以验证了,但是一定有同学不满意,test都不是window的成员,window是怎么调用它的,初学者不建议在往下看,记住上面的代码和结论就够了,在js里面每一个函数都有一个调用者,如果使用匿名的形式调用,浏览器会自动帮我们补全,怎么理解这个东西呢,函数的一般调用形式为obj.function(),如果简写成function(),浏览器会在运行的时候自动把函数临时加到当前作用域里面,并使用this.function()的方式调用,体现了js的运行时的特性

let test = function(){ console.warn('test', this) };
test();

//等价于下面的形式
let test = function(){ console.warn('test', this) };
test.call(this)

也就是使用Function原型中的call方法把this直接设置为了当前的this,而在script标签里面this就是window,实际上所有一般的调用形式都会被转化为call,下面的demo.test()等价于demo.test.call(demo)


let demo = {};
demo.test = function(){ console.warn('test', this) };
demo.test();
//输出test {test: ƒ}

let demo = {};
demo.test = function(){ console.warn('test', this) };
test();
//输出test is not defined

let demo = {};
let test = function(){ console.warn('test', this) }; 
demo.test = test;
test.call(demo);
//输出test {test: ƒ}

let demo = {};
demo.test = function(){ console.warn('test', this) };
demo.test.call(demo);
//输出test {test: ƒ}

 所以其实上面的结论可以表述为,函数的this指向call函数的第一个参数,也就是call的第一个参数是谁,函数的this就指向谁,有错误的地方欢迎大家批评指正,有不懂可以问我

//立即执行函数的写法
(function(){ 
    console.warn('test', this) 
})()

//等价于
let any = function(){ 
    console.warn('test', this) 
}

any();

这种调用方法咋一看挺唬人,其实是对匿名函数的匿名调用的简写,记住那个原则谁调用函数,函数的this就指向谁,如果以一般形式obj.function()出现(有的地方称为显式绑定),那函数this指向obj,如果以匿名形式function()出现(有时称为隐式绑定),那么指向当前作用域的this,大部分时候指向window,如果拿不准就转成call的写法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

free5156

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值