一、call、apply、bind的区别
call、apply、bind都是改变this指向的方法。
call
和 apply
的区别在于传递参数的方式不同:
apply
的第2
个参数为数组call
则是从第2
个至第N
个都是给func
的传参
bind
和 call
、 apply
的区别在于函数是否立即执行:
call
、apply
是在改变了函数的this
指向之后立马执行bind
会返回一个函数,虽然改变了func
的this
指向,但不是马上执行, 而是调用返回的函数才执行
二、call、apply、bind的使用
一、apply
1、获取数组最值
可以通过apply来获取Math.max()最大值和Maxth.min()最小值
let arr = [1, 2, 3];
const max = Math.max.apply(null, arr); // es6 Math.max(...arr)
const min = Math.min.apply(null, arr); // es6 Math.min(...arr)
console.log(max); // 3
console.log(min); // 1
//对比 简单循环算法
max = -Infinity, min = +Infinity;
for (var i = 0; i < arr.length; i++) {
if (arr[i] > max)
max = arr[i];
if (arr[i] < min)
min = arr[i];
}
// 使用apply参数过多时,达到引擎的上限时,传入的参数会被截取,不是完整的数组,可使用将数组切块后循环传入目标方法:
function minOfArray(arr) {
var min = Infinity;
var QUANTUM = 3;
for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
min = Math.min(submin, min);
}
return min;
}
var min = minOfArray([5, 6, 2, 3, 7]); // 2
var min = minOfArray([5, 6, 2, 3, 1]); // 1
// 运行结果
二、call
1、判断数据类型
可以通过Object.prototype.toString.call来判断所有数据类型
Object.prototype.toString.call(value)
1.判断基本类型:
Object.prototype.toString.call(null);//”[object Null]”
Object.prototype.toString.call(undefined);//”[object Undefined]”
Object.prototype.toString.call(“abc”);//”[object String]”
Object.prototype.toString.call(123);//”[object Number]”
Object.prototype.toString.call(true);//”[object Boolean]”
2.判断原生引用类型:
函数类型
Function fn(){console.log(“test”);}
Object.prototype.toString.call(fn);//”[object Function]”
日期类型
var date = new Date();
Object.prototype.toString.call(date);//”[object Date]”
数组类型
var arr = [1,2,3];
Object.prototype.toString.call(arr);//”[object Array]”
正则表达式
var reg = /[hbc]at/gi;
Object.prototype.toString.call(arr);//”[object RegExp]”
自定义类型
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person("Rose", 18);
Object.prototype.toString.call(person); //”[object Object]”
很明显这种方法不能准确判断person是Person类的实例,而只能用instanceof 操作符来进行判断,如下所示:
console.log(person instanceof Person);//输出结果为true
3.判断原生JSON对象:
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是
2、将类数组转为数组
类数组因为不是真正的数组,所有没有数组类型上自带的种种方法,所以要转为数组,才能调用数组的方法.
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
let arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
3、遍历NodeList数据
document.querySelectorAll()
返回的并不是我们想当然的数组,而是 NodeList
,对 NodeList
,它里面没有 .forEach
方法,我们使用了这样的方法进行循环:
var divs = document.querySelectorAll('div');
[].forEach.call(divs, function(div) {
// do whatever
div.style.color = "red";
});
原先的foreach方法可以接收一个参数
[1,2,3].forEach(function (num) { console.log(num); });
通过上面的代码,可以访问到this对象,是指向[1,2,3]的,也就是一个数组。
.call是一个prototype,JavaScript内置的,它的第一个参数就是改变this指向,
[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"
因此, [].forEach.call()
是一种快速的方法访问 forEach
,并将空数组的 this
换成想要遍历的list。
三、bind
window.color = 'red';
var str = {color: 'yellow'}
function sayColor() {
console.log(this.color,'say')
}
var objSayColor = sayColor.bind(str)()
// yellow 'say'
var objSayColor = sayColor.bind(this)()
// red 'say'
学习链接:
https://www.runoob.com/w3cnot...
四、延伸点
①prototype
, __proto__
原型与原型链
学习链接:javascript——原型与原型链
②构造函数
学习链接:构造函数
③作用域
学习链接:作用域
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。