优雅的改变this指向 call() bind() apply()
call 字面意思呼叫 apply 是应用 bind是捆绑的意思 这个最特别也是我们最常用的
fun.call(thisArg,arg1,arg2,...) //第一个参数是把this指向谁,后面的是其他类型参数
// call的作用 1是调用函数 2是改变this指向
// 主要作用是实现继承 在es5的时候
function run(a,b) {
console.log(this);
console.log(a+b);
}
var o = {
name: 'zhangsan'
}
// run.call() // 这样也能调用函数,没有修改this指向
// run.call(o) // 改变this指向为o
run.call(o,1,2)
function Father(name, age) {
this.name = name,
this.age = age
}
function Son(name, age) {
Father.call(this,name,age) //修改this指向为Son
}
var son = new Son('ldh',18)
console.log(son); // Son {name: "ldh", age: 18}
fun.apply(thisArg,[argsArg]) //第一个参数是把this指向谁,后面必须写成数组
apply的作用 1是调用函数 2是改变this指向
主要作用是如 对数组求最大值,数组本身没有求最大值得方法,但是Math有,我们通过apply改变下指向为Math
function run() {
console.log(this);
console.log(arguments); // 12 'pink',如果数组中传入的是number,输出的也是数字型,如果传入的是str那么输出的也会是字符串
}
var o = {
name: 'zhangsan'
}
// run.apply() // 也能调用函数
// run.apply(o) //改变this指向为o
run.apply(o,[12,'pink'])
var arr = [1,543,47,8,686,3]
var max = Math.max.apply(Math,arr) // 改变this指向为Math ,然后第二个参数需传入数组
console.log(max);
bind是重点需要掌握的!!!!
fun.bind(thisArg,arg1,arg2,...) //第一个参数是把this指向谁,后面其他参数类型
bind的作用 1不会不会不会调用函数 2 是改变this指向 3,会返回一个新的函数
主要作用是 不需要立即执行的时候我们就需要想到bind这是我们最常用的方式 如一个按钮点击的时候就禁用,三秒之后才会启动
function run (a,b) {
console.log(this);
console.log(a + b);
}
let p = {
name: 'zhangsan'
}
let f = run.bind(p) // 只是改变this指向,不会调用函数
f() //会返回一个新的函数
let f2 = run.bind(p,1,2)
f2()
// 经典
<button>点击</button>
<button class="btn">点击1</button>
<button class="btn">点击2</button>
<button class="btn">点击3</button>
var btn = document.querySelector('button')
btn.onclick = function() {
this.disabled = true // 点击后禁用
// setTimeout(()=>{ // 操 这里是箭头函数无this指向,指向的是上级的this ,上级就是btn实例
// // btn.disabled = false
// this.disabled = false
// },2000)
setTimeout(function(){
// btn.disabled = false // 这样有很多弊端,一旦按钮多一百个之后 ,显然这样写不科学
// this.disabled = false // 此时这里的this,是指向的是window ,启用无效
this.disabled = false
}.bind(this),2000) // 我们需要的是不立即执行,但是需要改变的是this指向,故采用bind,我们这里的bind是写在定时器函数的外部,在btn函数内部,故bind(this)这里的this 指的是当前点击的按钮实例
}
// 点击多个按钮,实现禁用启用
var btn1 = document.querySelectorAll('.btn')
var len = btn1.length // 类似做过dom查询做缓存
for(let i = 0;i<len;i++) {
btn1[i].onclick = function() {
this.disabled = true
setTimeout(function(){
this.disabled = false
}.bind(this),2000)
}
}