作用域绑定

一、作用域绑定

先看下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
var name="afei";
var age="28";

var A={
name:"alan",
A_age:this.age,
getInfo:function(){
console.log(this.name+"的年龄是"+this.age);
}
};


A.getInfo();//alan的年龄是undefined

这就是作用域改变的例子,在getInfo中的this指向A,而A中没有age属性。

再看下一个例子

1
2
3
4
5
var name="afei";
function B(){
console.log(this.name);
}
B();//afei

这时的this指向的是全局变量window。

那么如何能改变this指向的作用域呢,传统的方式有bind、apply、call。应用如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var name="afei";
var age="28";

var Test={
name:"alan",
A_age:this.age,
getInfo:function(from,to){
console.log(this.name+"的年龄是"+this.age+"来自"+from+"去往"+to);
}
};

var A={
name:"A",
age:11,
}
var B={
name:"B",
age:22,
}

Test.getInfo.call(A,"河南","浙江");//A的年龄是11来自河南去往浙江
Test.getInfo.call(this,"河南","浙江");//afei的年龄是28来自河南去往浙江
Test.getInfo.apply(A,["河南","浙江"]);//B的年龄是22来自河南去往浙江
Test.getInfo.bind(A,"河南","浙江")();//A的年龄是11来自河南去往浙江

简单可知:

  • call、bind、apply接受第一个参数就是this指向的上下文
  • call的接收的原始参数不变,apply接收的原始参数以数组形式传递
  • bind处理返回的是函数外其余的与call一样
  • bind返回的是函数,还需要执行

还有一种不需要局部绑定this的方法,那就是使用箭头函数

二、箭头(arros)函数

2.1 语法更简洁

常规语法定义函数

1
2
3
function func(arg1){
return arg1*5;
}

使用箭头函数则只需要一行代码

1
var func=(args)=>args*2;
2.2 箭头函数语法

箭头函数的语法如下

1
(parameters)=>{statements}

如果没有参数则可以直接写成

1
()=>{statements}

如果只有一个参数

1
parameter=>{statements}

如果返回值仅仅是一个表达式(expression),可以省略大括号

1
2
3
4
5
parameter=>expression
//等价于
function (parameter){
return expression;
}
2.3 与this的关系

箭头函数不会绑定this,即箭头函数不会改变this的本来绑定

例如,想再函数内部实现递增效果,需要有this的局部绑定,不然的话setInterval调用中的this就会绑定给全局变量,从而不能得到正确的count。

1
2
3
4
5
6
7
8
9
10
11
function CounterTest(){
this.count=0;
let that=this;
this.timer=setInterval(function add(){
that.count++;
console.log(that.count);
},1000);
}

//执行new CounterTest(),就会一直执行累加计算
//如果不绑定this,会打印Nan

如果不要局部绑定,不用call、apply、bind等方式,还有什么方法呢,就是箭头函数

1
2
3
4
5
6
7
function CounterTest(){
this.count=0;
this.timer=setInterval(()=>{
this.count++;
console.log(this.count);
},1000);
}

可以看出,CounterTest构造函数绑定的this会被保留,在setInterval函数中的this依然是CounterTest的作用域。

参考: