1. call 方法的使用:函数方法名.call(this指向谁,实参)
let func = function (x, y) {
this.sum = x + y;
};
window.name = "HELLO~";
let obj = {
name: '张三'
};
func.call(obj, 10, 20);
console.log(obj);//{name: "张三", sum: 30}
2. apply 方法的使用:函数方法名.apply(this指向谁就是谁,数组)
let func = function (x, y) {
this.sum = x + y;
};
window.name = "HELLO~";
let obj = {
name: '张三'
};
func.apply(obj,[10,20]);
console.log(obj);//{name: "张三", sum: 30}
3. bind方法的使用:f2相当于创建了一个func这个函数,但是this指向了obj,但是f2没有立即执行,需要手动执行
let func = function (x, y) {
this.sum = x + y;
};
window.name = "HELLO~";
let obj = {
name: '张三'
};
var f2=func.bind(obj,10,20);
f2();
console.log(obj);//=>{name: "张三", sum: 30}
4.call 和apply的区别?
- 1.CALL方法:让函数执行,改变函数中THIS指向的
- 2.APPLY方法:和CALL方法的作用一样,唯一的区别就是传递给函数的参数方式不一样
- 3.CALL方法是把实参信息一个个的传递进来 fn.call(context,params1,params2...)
- 4.APPLY传参方式是传递一个数组进来,但是也相当于再给函数一项项的传参,语法上需要写成数组而已 fn.apply(context,[params1,params2...])
- 5.CALL的性能要比APPLY好一些,尤其是需要传递给函数的实参超过三个的时候,所以真实项目中使用CALL偏多;但是某些需求基于APPLY可以实现更好的效果;
5.需求实现数组中的最大值和最小值
1.用数学函数和剩余运算符
let arr = [10, 20, 14, 8, 25, 13, 16, 10],
max = 0,
min = 0;
max = Math.max(...arr);
min = Math.min(...arr);
console.log(max, min);//25 8
2.排序
let arr = [10, 20, 14, 8, 25, 13, 16, 10];
arr.sort((a, b) => a - b);
max = arr[arr.length - 1];
min = arr[0];
console.log(max, min);//=>25 8
3.:apply:利用APPLY写成一个数组。利用APPLY虽然在语法上是写成一个数组,但是和CALL一样,也是把数组中的每一项传递给函数(Math.max这些方法执行的时候和THIS没关系,所以THIS改成啥都行)
let arr = [10, 20, 14, 8, 25, 13, 16, 10];
max = Math.max.apply(null, arr);
min = Math.min.apply(null, arr);
console.log(max,min);//=>25 8
4.假设法,假设数组中的第一项就是最大值或者最小值,然后拿这个值分别后后面的每一项进行比较,一旦发现比他大的,说明假设失败,让当前最大值替换原有假设的值即可
let arr = [10, 20, 14, 8, 25, 13, 16, 10];
max = min = arr[0];
for (let i = 1; i < arr.length; i++) {
let item = arr[i];
item > max ? max = item : null;
item < min ? min = item : null;
}
console.log(max,min);//=>25 8
6.把类数组变为数组
题目:
// 1.函数实参集合ARGUMRNTS(类数组集合)
// 2.不是数组是一个对象 arguments.__proto__:Object.prototype
// 3.arguments.length传递实参个数
// 4.arguments[0]获取第一个传递的实参信息
{
0:10,
1:20,
2:30,
length:3,
__proto__:Object.prototype
}
1.基于内置方法Array.from
function func() {
console.log(Array.from(arguments));
}
func(10, 20, 30);//=>[10, 20, 30]
2.方法2:直接...展开即可(把ARGUMRNTS中每一项都放置到一个新数组中)
function func() {
let arr = [...arguments];
console.log(arr);
}
func(10, 20, 30);//=>[10, 20, 30]
3.基于Array执行直接创建数组(把ARGUMRNTS中的每一项分别传递会ARRAY)
function func() {
console.log(Array.apply(null, arguments));
}
func(10, 20, 30);//=>[10, 20, 30]
4.自己写一个循环
function func() {
let arr = [];
for (let i = 0; i < arguments.length; i++) {
arr.push(arguments[i]);
}
console.log(arr);
}
func(10, 20, 30);//=>[10, 20, 30]
5.借用数组原型上的SLICE方法,让SLICE方法执行的时候,方法中的THIS变为要操作的类数组ARGUMENTS,这样就等价于ARGUMENTS利用数组中指定方法的代码完成一些自己要操作的需求(ARGUMENTS和数组解构很相似,所以能操作数组的代码,一般也能操作ARGUMENTS这种类数组的)
- 1.找到原型上的SLICE:
- 2.Array.prototype.slice
- 3.[].slice => [].proto.slice
//1.this操作
Array.prototype.slice = function slice() {
// this:操作数组实例(要克隆的数组)
// 模拟的内置SLICE代码
let arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(this[i]);
}
// 如果我们能够把Array.prototype.slice方法执行,并且让方法中的THIS
//变为要操作的类数组(例如:ARGUMENTS),就相当于在遍历类数组中的每一项,
//把每一项内容存放到新的数组中,实现了把类数组转换为数组
return arr;
};
let arr = [10, 20, 30];
// 数组克隆
let arr2 = arr.slice();
console.log(arr2);//=>[10, 20, 30]
//2.arguments操作
Array.prototype.slice = function slice() {
// 把arguments转换为数组的代码
let arr = [];
for (let i = 0; i < arguments.length; i++) {
arr.push(arguments[i]);
}
return arr;
};
let arr = [10, 20, 30];
console.log(arr);//=>[10, 20, 30]
6.除了能借用SLICE,数组的大部分方法都可以借用过来使用的
function func() {
[].forEach.call(arguments, item => {
console.log(item);
});
}
func(10, 20, 30);