一、函数内部的this指向
调用方式 | this指向 |
普通函数调用 | window |
构造函数调用 | 实例对象 |
对象的方法调用 | 该方法所属对象 |
事件绑定方法 | 绑定事件对象 |
定时器函数 | window |
立即执行函数 | window |
1、普通函数调用
普通函数的this指向window
1 function fun() { 2 console.log('普通函数的this' + this); 3 } 4 fun();
2、构造函数调用
构造函数this指向ldh这个实例对象,原型对象里面的this指向的也是ldh这个对象
1 function Star() {}; 2 Star.prototype.sing = function() {}; 3 var ldh = new Star();
3、对象的方法调用
对象的方法的this指向的是对象o
1 var o = { 2 sayHi: function() { 3 console.log('对象方法的this' + this); 4 } 5 } 6 o.sayHi();
4、事件绑定方法
绑定事件函数this指向的是函数的调用者btn这个按钮对象
1 var btn = document.querySelector('button'); 2 btn.onclick = function() { 3 console.log('绑定事件函数的this' + this); 4 5 }
5、定时器函数
定时器函数this指向的是window
1 setTimeout(function() { 2 console.log('定时器函数的this' + this); 3 }, 1000);
6、立即执行函数
立即执行函数this指向的是window
1 (function(){ 2 console.log('立即执行函数的this'+this); 3 })();
二、改变函数内部的this指向的三种方法
1、call方法
call()方法可以调用函数,还可以改变函数内的this指向,它的主要作用是可以实现继承
fun.call(thisArg,arg1,arg2,....)
这里将fun函数的this指向o
1 var o = { 2 name: 'Andy' 3 } 4 5 function fun(a, b) { 6 console.log(this); 7 console.log(a + b); 8 } 9 fun.call(o, 1, 2);
将父构造函数里的this指向子构造函数的实例对象(构造函数的this指向它的实例对象)
1 function Father(uname, age, sex) { 2 this.uname = uname; 3 this.age = age; 4 this.sex = sex; 5 } 6 7 function Son(uname, age, sex) { 8 Father.call(this, uname, age, sex); 9 } 10 var son = new Son('ldh', 18, 'male'); 11 console.log(son);
2、apply方法
fun.apply(thisArg,[argsArray])(传递的值必须包含在数组里)
apply()方法可以调用函数,还可以改变函数内的this指向,但它的参数必须是数组(伪数组)
1 var arr = [1, 33, 22, 44, 12]; 2 var max = Math.max.apply(Math, arr); 3 var min = Math.min.apply(Math, arr); 4 console.log(max, min);
3、bind方法(用的最多)
bind()方法不会调用函数,但是可以改变函数内部this指向
fun.bind(thisArg,arg1,arg2,....)
1 var o = { 2 name: 'Andy' 3 } 4 5 function fun(a, b) { 6 console.log(this); 7 console.log(a + b); 8 } 9 var f = fun.bind(o, 1, 2); 10 f();
下面的小案例是点击按钮后按钮禁用,直到三秒后开启按钮
虽然定时器函数里的this指向window,但是bind(this)里面的this是在定时器函数的外面绑定的,这个this又在btns[i].onclick这个函数里面,所以这个this指向的就是btns对象
为什么这里的this.disabled的this不用btns[i]呢,因为定时器是在3秒后执行,而for循环立马执行,这里有三个按钮,则i为3
1 var btns = document.querySelectorAll('button'); 2 for (var i = 0; i < btns.length; i++) { 3 btns[i].onclick = function() { 4 this.disabled = true; 5 setTimeout(function() { 6 this.disabled = false; 7 }.bind(this), 3000); 8 } 9 }
3、call、apply、bind总结
相同点:都可以改变函数内部的this指向
区别:
1.call和apply会调用函数,并且改变函数内部的this指向
2.call和apply传递的参数不一样,apply必须以数组形式
3.bind不会调用函数,但是会改变函数内部的this指向
主要应用场景:
1.call主要用作继承
2.apply经常跟数组有关,比如借助数学对象实现数组中的最大最小值
3.bind可用于改变定时器内部的this指向