call 作用:1.修改this指向
var o = {
name: 'ZS'
};
//构造函数
function fn(a = 10, b = 6) {
console.log(this);
console.log(a + b);
}
fn.call(o, 5, 3);
call 作用:2.用作继承
//这是es5通过构造函数实例化对象的语法
//父构造函数
function Father(name, age) {
this.name = name;
this.age = age;
}
Father.prototype.say = function () {
console.log("我是father的say");
}
//子构造函数
function Son(name, age, score) {
Father.call(this, name, age)
this.score = score;
}
Son.prototype = new Father();//让子类的原型对象指向父类实例, 这样一来在子实例中找不到的属性和方法就会到原型对象(父类实例)上寻找
//Son.prototype.constructor = Son;// 根据原型链的规则,顺便绑定一下 constructor, 这一步不影响继承, 只是在用到constructor时会需要
var s = new Son('张三', 13, 80)
console.log(s);
s.say()
apply 作用:也是改变this指向 传的参数是数组
var o = {
name: 'zhangsan'
}
function fn(a, b) {
console.info(this)
console.log(a + b);
}
fn.apply(o, [2, 5])
//求数组最大最小值
console.log(Math.max.apply(Math, [2, 34, 5]));
console.log(Math.min.apply(Math, [2, 34, 5]));
bind 作用:也是改变this指向, 但是bind不会立即执行
var o = {
name: 'zhangsan'
}
function fn(a, b) {
console.info(this)
console.log(a + b);
}
var f = fn.bind(o, 2, 3)
f()
demo:点击按钮禁用,2s后可以点击
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
document.querySelectorAll('button').forEach(function (item) {
item.onclick = function () {
this.disabled = true
//箭头函数this没有问题
// setTimeout(() => {
// this.disabled = false
// }, 2000)
//不用箭头函数,使用bind改变this指向
setTimeout(function () {
this.disabled = false
}.bind(this), 2000)
}
})
---------------------------------------------------------总结---------------------------------------------------------
相同点:
都可以改变函数内部this指向
区别点:
1.call和apply 会调用函数,并且改变函数内部this指向
2.call和apply 传递参数不一样,call传递参数 aru1,aru2...形式 apply 必须数组形式[arg]
3.bind 不会调用函数,可以改变函数内部this指向
应用场景:
1.call 经常做继承
2.apply 经常给数组有关系,比如借助数学对象实现数组最大值最小值
3.bind 不调用函数,但是还想改变this指向,比如改变定时器内部的this指向
网友评论