我们知道 this 一般根据所处位置区分为两种情况:
函数外面在全局上下文下 指的是全局对象
函数里面的是函数上下文 (这个函数上下文有多种情况这里不做描述)
也知道call 和 apply是可以改变函数内部的this对象。
最简单的例子是这样。
name = "kevin" var o= {name: "kev"} function ouputName () { console.log(this.name) } outputName(); //输出的是 "kevin" outputName.call(o); //输入的是 "kev"
上面就是通过call方法改变this的值。普通的函数里面的this,可以简单的理解为谁调用这个函数,this对象就是谁。
这不是重点,重点是 还有一个方法 methos.bind(thisArg, [parames]).
这个方法会返回一个和调用它的函数的同样函数体和作用域的函数,并且只会生效一次。this对象会被永久绑定到第一个参数上面,后面多次改变this是无效的。
例子:
name = "kevin" var o= {name: "kev"} function ouputName () { console.log(this.name) } outputName(); //输出的是 "kevin" outputName.call(o); //输入的是 "kev" //我们接着上面的例子来 var newO = {name: "Kesha"} var newFunc = outputName.bind(newO) //返回的函数和outputName是同样的函数体, this对象是newO newFunc() //输出的是 "Kesha" //重点是,这时候这个函数上下文永久的绑定到了newO对象上,this指向这个对象。 newFunc.call({name: "Catherine"}) //输出的仍然是"Kesha"
bind的特殊之处就是,返回函数的作用域永久的被绑定到了第一个参数上,后面用call, apply, bind都是不生效的。
那么问题来了,这样有什么用?其实主要是函数声明的时候是由我们决定的,但是函数执行的时候this 确实可以被动态修改的。这时候可能就需要bind函数固定this 上下文。
看例子:
var o = {
name: 'kevin',
sayHi: function() {
console.log('Hi. My name is '+ this.name)
}
}
我们创建了一个对象,o,o.sayHi() 1秒中之后,输出 'Hi, My name is kevin'
好,我们想时隔两秒,再打招呼,代码这样:
setTimeout(o.sayHi, 2000)
//oops 打印出来的是确是 Hi, My name is unidefined
sayHi函数丢失了this(obj)的绑定,而是绑定到了这个this(window对象),所以我们需要从新绑定this
setTimeout(o.sayHi.bind(o), 2000)