var uname = '张三';
var obj = {
uname: '李四',
say: function() {
console.log(this.uname);
}
}
obj.say(); //李四
setTimeout(obj.say, 0) //张三
最后的结果如下:

obj.say()输出的结果是李四,说明这里的this第一次调用的时候指向的是obj。而setTimeout(obj.say, 0)这里面的this指向的是window。
通过bind()改变this指向:
var uname = '张三';
var obj = {
uname: '李四',
say: function() {
console.log(this.uname);
}
}
obj.say(); //李四
setTimeout(obj.say, 0) //张三
setTimeout(obj.say.bind(obj), 0) //李四

apply的使用:两个参数,第一是this的指向,第二个是函数接收的参数,以数组的形式传入
//apply:两个参数,第一是this的指向,第二个是函数接收的参数,以数组的形式传入
function fun(...argus) {
console.log(this);
console.log(...argus);
}
var person = {
myname: '王五'
}
fun.apply(person, [1, 2, 3, 4]); //传入的参数必须是一个数组
fun(1, 2, 3, 4)
//如果第一个参数null或者undefined,this默认指向window
fun.apply(null, [1, 2])
fun.apply(undefined, [1, 2])
结果为:

call的使用:两个参数,第一是this的指向,第二个是参数列表
function fun(...argus) {
console.log(this);
console.log(...argus);
}
var person = {
myname: '王五'
}
fun.apply(person, [1, 2, 3, 4]); //传入的参数必须是一个数组
fun(1, 2, 3, 4)
//如果第一个参数null或者undefined,this默认指向window
fun.apply(null, [1, 2])
fun.apply(undefined, [1, 2])
console.log('---------------')
fun.call(person, 1, 2, 3, 4)

call()和apply()改变this的指向以后,它的原函数会立即执行,临时改变this指向一次。
bind的使用:两个参数,第一是this的指向,第二个是参数列表。它改变this指向以后不会立即执行,它返回的是一个永久改变this指向的函数
function fun(...argus) {
console.log(this);
console.log(...argus);
}
var person = {
myname: '王五'
}
var bindFun = fun.bind(person)
bindFun(1, 2, 3, 4);
bindFun();

写法:
Function.call(obj,[param1[,param2[,…[,paramN]]]])
写法:
Function.apply(obj[,argArray])
Function.bind(thisArg[, arg1[, arg2[, ...]]])
bind 方法 与 apply 和 call 比较类似,也能改变函数体内的 this 指向。不同的是,bind 方法的返回值是函数,并且需要稍后调用,才会执行。而 apply 和 call 则是立即调用。
如果 bind 的第一个参数是 null 或者 undefined,this 就指向全局对象 window。
call 和 apply 的主要作用,是改变对象的执行上下文,并且是立即执行的。它们在参数上的写法略有区别。
bind 也能改变对象的执行上下文,它与 call 和 apply 不同的是,返回值是一个函数,并且需要稍后再调用一下,才会执行。