函数的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就指向谁,有错误的地方欢迎大家批评指正,有不懂可以问我