记住这几条规律,你就能弄懂JS中的this指向问题

关于Javacript中的this指向问题,我把它们总结为如下几个规律:

1.规律一:函数用圆括号直接调用,函数中的this指向window对象

function fun() {
   	var a = 100;
   	console.log(this.a);
 } 
 var a = 200;
 fun(); //200

解释:所有的全局变量都是window对象的属性、所有的全局函数都是window对象的方法。函数里面的局部变量,既不是window对象的属性,也不是其他任何东西的属性。如上例,fun()函数是window对象的方法,fun()等价与window.fun(),那么则是window对象调用了fun()方法,fun函数里面的this则指向调用者window对象。

2.规律二:函数如果是作为一个对象的方法,是对象打点调用,则函数里的this指向的就是该对象

function fun() {
   var a = 8;
   console.log(this.a);
}
var obj = {
   "a":10,
   "b":20,
   "c":fun
}
obj.c(); //10

3.规律三:如果函数是事件处理函数,则函数里的this指向触发这个事件的对象

function fun() {
	this.background.color = "red";
}
var box = document.getElementById("box");
box.onclick = fun; //点击box的时候,box会变成红色

4.规律四:定时器调用函数,this指向window对象

var a = 8;
function fun() {
	var a = 80;
	console.log(this.a);
}
setInterval(fun, 1000); //8

但是需要注意的是,如果定时器在闭包当中,定时器中的this还是指向window对象

var box = document.getElementById("box");
box.onclick = function() {
    setTimeout(function(){
        this.style.background = "red"; //点击之后,box并没有变成红色,而window对象也不能设置背景色
    }, 1000);
}

5.规律五:数组中存放的函数,被数组索引调用,函数中的this指向数组本身

function fun() {
    console.log(this);
}
var arr = [fun,"东风",2];
arr[0](); //arr数组

6.规律六:ES6新增的箭头函数,this不是指向调用时所在的对象,而是在指向定义时所在的对象
如果你对箭头函数还不了解,可以参考我的这篇文章:ES6箭头函数简介
我们还是拿上面的那个定时器的例子来说明问题

var box = document.getElementById("box");
box.onclick = function() {
    setTimeout(() => {
        this.style.background = "red"; 
        //点击之后,box变成了红色,this指向了box,是因为箭头函数是在box对象里面定义的
    }, 1000);
}

根据以上6个规律,不难发现其本质:
a.当函数没有被调用的时候,函数中的this指向是不明确的,也就是说只有知道函数是怎么调用的,被谁调用的,才能确定this的指向;
b.谁直接调用了该函数,那么该函数中的this就指向谁,其中要注意是谁直接调用的,在规律四闭包中的函数里的this还是指向window,那是因为定时器是被window直接调用的,而不是最外部的box;
c.如果在箭头函数中,以上的经验并不适合,箭头函数指向了定义时所在的对象。

7.关于call()和apply()
a.首先这两个方法都是函数的方法,也就是说只有函数才能调用这两个方法;
b.这两个方法的作用都是用指定的上下文来执行函数。

function fun() {
    console.log(this.age);
}
var obj = {
    "name":"小明",
    "age":12
}
fun.call(obj);    //12 这里传递obj进去作为第一个参数,让fun里的this发生了改变,指向了obj

c.这两个方法的区别在于传递的参数形式不一样,call()直接写参数列表即可,apply()则需要传递一个数组

fun.call(obj, 6, 7, 8);
fun.apply(obj, [6,7,8]);

那么我们很容易想到apply这种传递参数的方式的可用之处,
如果我现在要求一个数组中的最大值就变得很容易:

var numMax =  Math.max.apply(window, [4,20,7,288]); 
console.log(numMax); //288 

8.小题一试

function fun(m, n ,o, p, q, r) {
	console.log(this.length);
}
function f(a, b) {
	arguments[0](9, 10, 11, 12, 13, 14);
}
f(fun, 5, 6, 7);
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值