this关键字在JavaScript中扮演了至关重要的角色,每次它的出现都伴随着它的指向问题,这也是很多初学者容易出错的地方。
不过,这篇文章将会带你一次性搞定this指向的问题,望能给大家提供帮助!
一、谁最终调用函数,this就指向谁!
这句话是需要牢记的口诀,将this的指向问题转换为分析确定函数最终调用者的问题,以下是对这句话的解释和补充:
① this指向谁,不应该考虑函数在哪里里声明的,而是应该考虑函数在哪调用;
② this指向的永远是对象,而不可能是函数。
③ this指向的对象叫做函数的上下文(context),也叫函数的调用者。
那么问题又来了,函数的最终调用者如何确定呢?我们先来看一个面试题:
- 阅读如下代码,输入的结果应该是?
- var length = 10
- function 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 = 10
- function 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]());
- // 函数最终调用者数组
如有错误,欢迎大家指正交流!谢谢!
来源: http://www.cnblogs.com/wq1994/p/7672565.html