this指向及改变this指向的方法
任何函数都有属于自己的this
函数的调用方式决定了this的指向
一、this指向window
1)、普通函数(声明式函数)调用,此时this指向window
2)、 箭头函数没有自己的this,它的this指向上下文中的this(即所处环境的this)
3)、赋值式函数调用,此时this指向window
4)、定时器函数,指向window
//普通函数(声明式函数)
function fn(){
console.log(this);//指向window
}
fn();
//赋值式函数
var fun = function(){
console.log('fun',this);//指向window
}
fun();
//箭头函数
var fun2 = aa=>{
console.log(this);//指向window
}
fun2();
//定时器函数
setInterval(function () {
console.log(this); // window
}, 1000);
二、this指向所属(实例)对象
1)、构造函数被调用,this指向实例对象 ( 创建出来的实例 )
2)、事件绑定的的函数,指向绑定事件的对象 ( 触发事件的元素 )
//构造函数
function Person (name,home){
this.name = name
this.home = home
console.log(this);this指向Person ↓
//Person {name: "海绵宝宝", home: "比奇堡"}
}
var beach = new Person('海绵宝宝','比奇堡')
------------------------
//如果函数作为对象的一个属性时,称之为方法,当这个方法被调用时,this被绑定到当前对象
var obj = {
test:function(){
console.log(this); //{test: ƒ}
}
}
obj.test()
//事件
<body>
<button id="btn">hh</button>
<script>
var oBtn = document.getElementById("btn");
oBtn.onclick = function() {
console.log(this); // btn
}
</script>
</body>
三、this指向可以改变
改变函数内this指向,js提供了三种方法 call() , apply() , bind()
//全局name为 Tom
var name = 'Tom';
function animal(){
return this.name;
}
var o = {
'name':'Jerry',
animal:animal
};
console.log(animal()); //this.name 为Tom
console.log(animal.call(o)); //用call将this指向 o变量,使this.name 为Jerry
console.log(animal.apply(o)); //用apply将this指向 o变量,使this.name 为Jerry
call() 方法
call 第一个作用是可以调用函数 第二个可以改变函数内的this 指向
call 的主要作用可以实现继承
call 第一个参数是指向的对象,第二个参数是函数的参数
var o = {
name: 'Tom'
}
function fn(a, b) {
console.log(this); //指向对象 {name: "Tom"}
console.log(a + b); //3
};
fn.call(o, 1, 2);
apply() 方法
第一个作用是调用函数 第二个可以改变函数内部的this指向
但是他的参数必须是数组(伪数组)
apply 的主要应用 比如说我们可以利用 apply 借助于数学内置对象求数组最大值
var o = {
name: 'Jerry'
}
function fn(a, b) {
console.log(this); //指向对象 {name: "Jerry"}
console.log(a[0]+a[1]); //3
};
fn.call(o, [1,2]);
----------------------------------------
var arr = [1, 666, 3, 99, 4];
var max = Math.max.apply(Math, arr);
var min = Math.min.apply(Math, arr);
console.log(max, min); //666 , 1
bind()方法
不会调用原来的函数,完成了函数和对象的绑定,并且产生一个新的函数(里面的this就是绑定的对象)
返回的是原函数改变this之后产生的新函数
如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind
//下面代码的效果:我一个按钮,点击之后,就禁用这个按钮,3秒钟之后开启这个按钮
var btn1 = document.querySelector('button');
btn1.onclick = function() {
this.disabled = true; // 这个this 指向的是 btn 这个按钮
// var that = this;
setTimeout(function() {
// that.disabled = false; // 定时器函数里面的this 指向的是window
this.disabled = false; // 此时定时器函数里面的this 指向的是btn
}.bind(this), 3000); // 这个this 指向的是btn 这个对象
}
四、面试题: call,apply和bind的区别。
相同点:它们都可以改变函数内部的this指向
不同点:
1、call 和 apply 会调用原本的函数,改变函数内部的this指向
2、call 和 apply 传递的参数不一样,call传递的参数是单个(a,b,c)形式,apply必须传递数组(伪数组))
3、bind 不会调用原来的函数,而是完成函数和对象的绑定,并且产生一个新的函数(里面的this就是绑定的对象)
主要应用场景
call() 方法经常用于继承。
apply()常用于操作数组,比如借助于数学内置对象求数组最大值、最小值
bind()不调用函数,但是还想改变this指向。比如改变定时器内部的this指向