先来看个Demo
function Person(name){
this.name = name;
this.sex = "m";
this.age = "20";
}
//定义实例方法introduceMe,otherMsg为该方法参数
Person.prototype.introduceMe = function(otherMsg="And I'm a student !") {
return `
Hello, everyBody !
myName is ${this.name};
mySex is ${this.sex};
myAge is ${this.age}
${otherMsg}
`
}
let lilei = new Person("lilei");
console.log(lilei.introduceMe())
/**
Hello, everyBody !
myName is lilei;
mySex is m;
myAge is 20
And I'm a student !
*/
function Fmail(name){
this.name = name;
this.sex = "f";
this.age = "18";
this.enjoy = "reading,playing...";
}
let hanxue = new Fmail();
//Fmail这个对象没有定义introduceMe方法,通过call可以调用
console.log(lilei.introduceMe.call(hanxue));
/**
Hello, everyBody !
myName is undefined;
mySex is f;
myAge is 18
And I'm a student !
*/
//hanxue这个Fmail的实例通过call调用introduceMe方法的同时,还可以传参
console.log(lilei.introduceMe.call(hanxue,"And I like reading !"));
/**
Hello, everyBody !
myName is undefined;
mySex is f;
myAge is 18
And I like reading ! --introduceMe传进的参数
*/
/**
apply的写法:
console.log(lilei.introduceMe.apply(hanxue,["And I like reading !"]));
bind的写法:
console.log(lilei.introduceMe.call(hanxue,"And I like reading !")());
*/
解析
call、apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向。call、apply和bind三者第一个参数都是 this 要指向的对象,也就是想指定的上下文;call、apply和bind三者都可以利用后续参数传参;bind是返回对应函数,便于稍后调用;apply、call则是立即调用 。bind和call接收参数序列(...args),apply接收数组参数(args)
方便理解:this即某对象实例(如demo中的hanxue),但该实例自身没有该方法,通过 方法.call(对象实例,参数) 即 lilei.introduceMe.call(hanxue) hanxue就可以调用introduceMe方法了。
扩展
当this指向null或undefined时会自动指向全局对象(浏览器中的window对象)
//所以某个函数的参数为序列时,可以这样用
let arry = [1,3,4,2,5];
Math.min.apply(null,array); //1
//现在当然用 ... 扩展运算符更为方便了
Math.min(...arry); //1