call apply bind 的理解存在的意义: 改变函数执行时上下文,改变this指向,代码复用。
apply接受两个参数,第一个参数指定了this对象的指向,第二个参数为带下标的集合,这个集合可以是数组或者是类数组,apply会把这个集合的元素作为参数传递给被调用的函数
call的参数不固定,第一个参数跟apply一样,代表函数体内的this对象的指向,第二个以后的参数会依次传递给函数
let obj = {
name:"张三"
}
function Child(name){
this.name = name
}
Child.prototype = {
constructor:Child,
showName:function(){
console.log(this.name);
}
}
let child = new Child('里斯')
child.showName()
//代码复用obj使用了Child方法
child.showName.call(obj)
child.showName.apply(obj)
let bind = child.showName.bind(obj)
bind()
区别
bind 不会立即执行 call apply可以立即执行
call apply 的区别参数不一样,call要逐个来写,apply支持数组
例子:
//需求:求数组里面的最大值
let arr1 = [1,2,33,442,9,34]
console.log(Math.max.call(null,1,2,33,442,9,34));
console.log(Math.max.call(null,arr1));
console.log(Math.max.apply(null,arr1));
实战应用
1.将类数组转化为数组
//获取元素后类数组
let div = document.getElementsByClassName('a')
// 但slice 方法不适用ie8以下
let arrDiv = Array.prototype.slice.call(div)
//[...div] 也存在兼容性问题
// console.log(arrDiv);
//如果就是要兼容ie8
function listArray(div){
let arr = []
try{
arr = Array.prototype.slice.call(div)
}catch(e){
for(let i=0;i<div.length;i++){
arr[arr.length] = div[i]
}
}
return arr
}
// console.log(listArray(div));
//arguments类数组转换
function fn(){
// return [...arguments]
return Array.prototype.slice.call(arguments)
}
console.log(fn(1,2,3,4,5));
// 类数组对象转换
let obj1= {
0:1,
1:'张三',
2:'李四',
length:3
}
let objArr = Array.prototype.slice.call(obj1)
//console.log(objArr);
2.数组的拼接
let arrA = [1,2,3]
let arrB = [4,5,6]
// let arrC = arrA.concat(arrB)
//concat不会改变原数组
//console.log(arrA);
//console.log(arrB);
// console.log(arrC);
// 但是如果就是想改变呢?
// 可以for循环push
// 可以apply方法
Array.prototype.push.apply(arrA,arrB)
console.log(arrA);
3.经典应用判断数据类型
let arrD= [1,2,34,4]
function isArray(a){
//return Object.prototype.toString.call(a) === '[object Array]'
//return Object.prototype.toString.call(a) === '[object Object]'
//return Object.prototype.toString.call(a) === '[object String]'
return Object.prototype.toString.call(a) === '[object null]'
}
console.log(isArray(arrD));