this关键字在JavaScript中扮演了至关重要的角色,每次它的出现都伴随着它的指向问题,这也是很多初学者容易出错的地方。
不过,这篇文章将会带你一次性搞定this指向的问题,望能给大家提供帮助!
一、谁最终调用函数,this就指向谁!
这句话是需要牢记的口诀,将this的指向问题转换为分析确定函数最终调用者的问题,以下是对这句话的解释和补充:
① this指向谁,不应该考虑函数在哪里里声明的,而是应该考虑函数在哪调用;
② this指向的永远是对象,而不可能是函数。 ③ this指向的对象叫做函数的上下文(context),也叫函数的调用者。那么问题又来了,函数的最终调用者如何确定呢?我们先来看一个面试题:
阅读如下代码,输入的结果应该是?var length = 10function fn() { alert(this.length)}var obj = { length: 5, method: function(fn) { fn() // ? arguments[0]() // ? }}obj.method(fn);
试着确定一下,题干中函数的最终调用者是谁?有了答案的话我们继续往下看:
★★★ 二、this指向的规律 :(跟函数的调用方式息息相关!)
① 通过 【 函数名() 】 调用的,this永远指向window;
② 通过 【 对象.方法 】调用的,this永远指向对象。obj.func(); ③ 函数作为数组中的 一个元素,通过数组下标调用的 【 arr[i]() 】,this指向数组arr。 ④ 函数作为window内置函数的回调函数使用,this指向window; setTimeout() setInterval()等 ⑤ 函数作为构造函数,使用new关键字调用,this指向新new出的对象。针对以上的规律我们分别举例说明:
① 通过 【 函数名() 】 调用的,this永远指向window;
function func () { console.log(this); } func();//函数名+()调用,this指向window
② 通过 【 对象.方法 】调用的,this永远指向对象。
var obj = { name:"wq"; func:func; } obj.func();//通过对象.方法调用的,this永远指向对象。
Window.onclick = function () { document.getElementById("zz").onclick = function () { func();//函数名+()调用,this指向window } document.getElementById("zz").onclick = func;//广义对象 通过对象.方法调用的,this永远指向对象 }
③ 函数作为数组中的 一个元素,通过数组下标调用的 【 arr[i]() 】,this指向数组arr。
var arr [1,2,3,func,4,5,6] arr[3]();//函数作为数组中的 一个元素,通过数组下标调用的 【 arr[i]() 】,this指向数组arr
④ 函数作为window内置函数的回调函数使用,this指向widow;
setTimeout(func,1000);//函数作为window内置函数的回调函数使用,this指向window;
⑤ 函数作为构造函数,使用new关键字调用,this指向新new出的对象。
var obj1 = new func()//函数作为构造函数,使用new关键字调用,this指向新new出的对象obj1。
var obj1 ={ name:"obj1", arr:[func,1,2,3,4] } obj1.arr[0]()//最终的调用者是数组。 setTimeout(obj1.arr[0],2000);//,作为内置函数进行调用,故this指向window;相当于setTimeout(func,2000);
在结合了相关实例对这几句话进行理解之后,我们再回过头来看一下上面的那道面试题:
阅读如下代码,输出的结果应该是?var length = 10function fn() { alert(this.length)}var obj = { length: 5, method: function(fn) { fn() // ? 10 arguments[0]() // ? 1 }}obj.method(fn);答案:fn() // 10 通过函数名()调用,this指向window,即全局变量length。 arguments[0]() // 1 函数作为数组中的 一个元素,通过数组下标调用的 【 arr[i]() 】,注意此时的数组是arguments,传入实参fn.
tips:
在JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。arguments非常类似Array,但实际上又不是一个Array实例。
arguments对象的长度是由实参个数而不是形参个数决定的。
最后我们再通过几道面试题来巩固下:
var fullname = 'John Doe'; var obj = { fullname: 'Colin Ihrig', prop: { fullname: 'Aurelio De Rosa', getFullname: function() { return this.fullname; } } }; console.log(obj.prop.getFullname()); // 函数的最终调用者 obj.prop var test = obj.prop.getFullname; console.log(test()); // 函数的最终调用者 test() this-> window obj.func = obj.prop.getFullname; console.log(obj.func()); // 函数最终调用者是obj var arr = [obj.prop.getFullname,1,2]; arr.fullname = "JiangHao"; console.log(arr[0]()); // 函数最终调用者数组
如有错误,欢迎大家指正交流!谢谢!