一、函数内部的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指向