this指向问题
this是在运行是绑定的,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
默认绑定(this指向全局对象window)
function f(){
console.log(this.a);
}
var a=2;
f();//2
在以上代码中,f()是不带任何修饰的函数引用进行调用的,所以是属于默认绑定
隐式绑定
function f(){
console.log(this.a);
}
var obj={
a:2,
f:f
}
obj.f()//2
这种情况是函数的引用有上下文对象的(obj对象的上下文),所以隐式绑定规则会把函数调用中的this绑定到这个上下文对象
function f(){
console.log(this.a);
}
var obj={
a:22,
f:f
}
var obj1={
a:2,
obj:obj
}
obj1.obj.f();//22
引用的是最接近的变量a
注意,将如上要调用的函数赋值给另外变量后,”隐式“会消失
以下3个例子都属于赋值操作,setTimeout()函数实现也是类似的
例一:
function f(){
console.log(this.a);
}
var obj={
a:22,
f:f
}
var other=obj.f;
var a=123
other();//123
例二:
function f(){
console.log(this.a);
}
function fun(func){
func();
}
var obj={
a:22,
f:f
}
var a=123
fun(f);//123
相当于将f赋值给func
例三:
function f(){
console.log(this.a);
}
var obj={
a:22,
f:f
}
var a=123
setTimeout(obj.f,100);//123
显式绑定
指定某个对象为函数调用时的this,call、apply、bind函数
call
function f(){
console.log(this.a);
}
var obj={
a:22
}
var other=function(){
f.call(obj)
}
other();//22
setTimeout(other,100);//22
apply
function f(b){
console.log(this.a,b);
return this.a+b;
}
var obj={
a:22
}
var other=function(){
return f.apply(obj,argumments)//argumments是固定变量,不能改名
}
var res=other(3);//22 3
console.log(res);//25
bind
function f(b){
console.log(this.a,b);
return this.a+b;
}
function bind(f,obj){
return function(){
return f.apply(obj,arguments)
}
}
var obj={
a:22
}
var other=bind(f,obj)
var res=other(3);//22 3
console.log(res);//25
new绑定
所有函数都可以用new来调用,new调用的过程见下文 使用new操作符创建构造函数的实例整个过程?
function f(a){
this.a=a;
}
var other=new f(2);
console.log(other.a);//2
注意
- this四条规则的优先级就不一一细说,new绑定>显式绑定>隐式绑定>默认绑定(可参考《你不知道的javaScript上》91~95页)
- 当call、apply、bind需要忽略this绑定时,可以传入null(但是会改变this绑定,函数中如果使用this会绑定到全局对象),可以用∅。
- 还有一种叫软绑定的(好像很复杂。。。。《你不知道的javaScript上》98 有空再看看吧)
- 特殊的箭头函数,箭头函数中的this指的是其外层作用域.
function f(a){ return (a)=>{ //这里面的this是f里的 console.log(this.a); } } var obj1={ a:1 } var obj2={ a:2 } var other=f.call(obj1); other.call(obj2);//1