函数调用方式不同 指向就不同
(1)普通函数 this指向window
function fu(){
console.log('普通函数调用:' + this);
}
Window.fn();
// window.fn.call()
(2)对象的方法 this指向的是对象o
var o = {
sayHai:function(){
console.log('对象方法调用:' + this);
}
}
o.sayHai();
(3)构造函数 this指向就是ldh的实例对象
只要调用构造函数就会产生一个新的实例对象
function Star(){};
Star.Prototype.sing = function(){}
var ldh = new Star();
(4)绑定事件函数 this 指向的是函数的调用者 btn这个按钮对象
var btn = document.querySelector('button')
btn.onclick = function(){
console.log('绑定时间函数的this' + this);
};//点击按钮就可以来调用这个函数
(5)定时器函数 this 指向的也是window
window.setInterval(function(){},1000); //这个函数是定时器自动1秒钟调用一次
(6)立即执行函数 this 指向的也是window
(function(){
console.log('我是立即执行函数调用');
})(); //立即执行函数是自动调用
Javascript 为我们提供了一些函数方法来帮我们更优雅的处理函数内部 this 的指向问题,常用的有 bind(), call(),apply() 三种方法
js提供 call ( ) , apply ( ),bind ( ) 三种方法:
1, call() 方法
var o1 = {
name: "admin"
}
function fn(a, b) {
console.log(this);
console.log(a + b);
};
fn.call(o1, 3, 4);
call 第一个可以调用函数 第二个可以改变函数内的this指向
call 的主要作用可以实现继承
function Father(uname, age, sex) {
this.uname = uname;
this.age = age;
this.set = sex
}
function Son(uname,age,sex) {
Father.call(this,uname,age,sex)
}
var son = new Son('刘德华','18','男');
console.log(son);
2, apply() 方法
var o2 = {
name: "apply"
}
function fn(arr){
console.log(this);
console.log(arr);
};
fn.apply(o2,['pink']);
(1)apply 第一个可以调用一个函数 第二可以改变函数内的this指向
(2)但是他的参数是个数组(伪数组)
(3)apply的主要应用 我们可以利用apply借助数学内置对象最大值
数学内置对象Math.max();
var arr = [1,66,3,99,4];
var max = Math.max.apply(null,arr); //比较最大值
var min = Math.min.apply(null,arr); //比较最小值
console.log(max); //99
console.log(min); //1
//简写console.log(max,min); // 99 1
3,bind() 方法 绑定 捆绑的意思
不会调用函数
var o3 = {
name: "bind"
}
function fn(a,b) {
console.log(this);
console.log(a+b);
};
var f = fn.bind(o3,1,2);
f();
(1)它不会调用原来的函数 可以改变原来函数内部的this的指向
(2)返回的是原函数改变this之后产生的新函数
(3)开发用的最多,如果有的函数我们不需要立即调用,就用它但又想改变这个函数内部的this 指向,此时用bind方法最合适的
需求案例:我们有一个按钮,当我们点击之后,就禁用这个按钮,3秒后开启这个按钮
以往的写法:
var btn = document.querySelector('button');
btn.onclick = function(){
this.disabled = true; //这个this指向的是btn这个按钮
var that= this;
setInterval(function(){
this.disabled = false; //定时器里面的this指向的是window
btn.disabled = false;
},3000)
}
上面案例换高级写法bind(this)
var btn = document.querySelector('button');
btn.onclick = function(){
this.disabled = true; //这个this指向的是btn这个按钮
setInterval(function(){
// this.disabled = false; //定时器里面的this指向的是btn
btn.disabled = false;
}.bind(this),3000)
// }.bind(btn),3000) 更神奇还可以将btn改成this,因为this是指向btn
//这里用call和apply都不行 ,因为我们不想立马调用,如果是多个按钮要用bind(this)
}
问题:是有多个按钮时,可用for循环来写
var btns = document.querySelectorAll('button');
for(var i = 0; i < btns.length; i++){
btns[i].onclick = function(){
this.disabled = true;
setInterval(function () {
this.disabled = false;
}.bind(this),2000)
}
}
// 总结:有了bind之后我们就不用在声明一个变量把他保存起来在使用了// var that= this;
This指向里面发方法:call、apply、bind总结一下:
相同点: 都是可以改变函数内部的this指向。
区别点:
(1)call和apply 会调用函数,并且改变函数内部this的指向
(2)call和apply传递的参数不同,call是参数1,参数2...形式;apply必须是数组形式【参数】
(3)bind不会调用函数,可以改变函数内部的this指向
主要应用场景:
1,call 经常用做继承
2,apply 经常跟数组有关系,借助数学对象实现数组最大值最小值
3,bind 不调用函数,但是还想改变this指向,如改变定时器内部的this指向