一:作用(与函数有关)
改变函数运行时的上下文
函数有
定义时上下文
,运行时上下文
和上下文可以改变
的概念
二:call和apply的区别
call接收的是一个一个的参数
apply接收的是数组
当传入的参数个数不确定时,用apply
三:一堆栗子
栗子1
function Fruits(){}
Fruits.prototype = {
color:'red',
sayColor:function(){
console.log("color is:"+this.color)
}
}
let apple = new Fruits();
apple.sayColor(); // red
这里有一个banana,但是我们不想给香蕉重复定义sayColor方法,就可以借用apple的,也就是改变了this
banana = {
color : 'yellow'
}
apple.sayColor.call(banana)
例子2
let func = function(arg1,arg2){}
func.call(this,arg1,arg2);
func.apply(this,[arg1,arg2]);
// 这里的this是你想指定的上下文,可以是任何JavaScript对象
// 剩下的参数与你想借用的函数的参数想对应
例子3——巩固apply(数组)
var obj = {
name : '小美女'
};
function func(first, last){
console.log(first + ' ' + this.name + ' ' + last); // a 小美女 b
}
func.apply(obj, ['a','b']);
1. 第一个参数是作为函数上下文的对象 , 这里将obj作为函数的对象,this指向了obj
2. 第二个参数是一个数组,这里数组中的参数分别对应函数的first 和 last
3. 将obj对象冒充进去了
例子4——巩固call(一个一个的参数)
var obj = {
name : '小美女'
};
function func(first, last){
console.log(first + ' ' + this.name + ' ' + last); // a 小美女 b
}
func.call(obj, 'a', 'b');
1. 第一个参数是作为函数上下文的对象 , 这里将obj作为函数的对象,this指向了obj
2. 第二个到第n个参数分别对应函数的参数们
3. 将obj对象冒充进去了
四:几个常考的例子
- 求数组的最大值和最小值
/*
* 获取数组的最大值和最小值
* Math.max(a,b,c...):一组数的最大值
* Math.min(a,b,c...):一组数的最小值
*
* 这两个函数对于数字组成的数组没法用
* 使用apply传入数组后,等于使用数组中的所有值作为函数的参数
*
* nums数组本身没有max和min方法,但是Math有此方法,所以借助call和apply来计算
* */
方法一:借助Math的max和min方法
let nums = [100,20,-199,33];
let maxNum = Math.max.apply(null,nums);
let minNum = Math.min.apply(null,nums);
console.log(maxNum); // 100
console.log(minNum); // -199
方法二:es6的扩展运算符
console.log(Math.max(...nums)); // 100
console.log(Math.min(...nums)) // -199
- 变量的类型
Object.prototype.toString.call(arr)
为什么用toString方法:
因为object.toString()的原型中是返回数据类型的,但很多实例中都改写了这一方法
let arr = [1,2,3];
// 检验在实例上是否有toString方法
console.log(Array.prototype.hasOwnProperty("toString")); // true
console.log(arr.toString()); // 1,2,3
delete Array.prototype.toString;
console.log(Array.prototype.hasOwnProperty("toString")); // false
console.log(arr.toString()); // [object Array]
3.将伪数组转化为真正的数组
// 将伪数组转化为真正的数组,因为伪数组没有slice方法,用此方法后可以将它转化成真正的数组
function toArray(obj){
return Object.prototype.slice.call(obj)
}
五:bind
bind方法类似于call,会新创建一个函数,称为绑定函数,调用绑定函数时,bind方法传入的第一个参数为this,剩下的参数作为原函数的参数来调用原函数
六:bind call apply比较
/*
* 三者比较
* 在改变上下文后并不是立即执行,就用bind
* */
let oo = {
x:1
}
let foo = {
getX : function(){
console.log(this.x)
}
}
foo.getX.call(oo);
foo.getX.apply(oo);
foo.getX.bind(oo)()
注意bind后面加了个括号表示执行
七:其他
1. 改变this的指向
var obj = {
name : "小美女"
};
function fn(){
console.log(this.name); // 小美女, this指向了object
}
fn.call(obj);
2. 借用别的对象的方法
var Person1 = function(){
this.name = '小美女';
}
var Person2 = function(){
this.getName = function(){
console.log(this.name); // 小美女
}
// console.log(this); // Person2中所有的
Person1.call(this); // 使用Person1对象代替this,相当于Person2继承了Person1的属性好方法
}
var person = new Person2();
person.getName();
// person 是Person2的一个实例
// person继承了Person2所有的属性和方法getName
3. 调用函数
function abc(){
console.log('abc');
}
abc.call(); // call和apply都可以用来调用函数,使函数立即执行