参考:https://segmentfault.com/a/1190000009556703#articleHeader3
在ES6中,箭头函数this指向定义时的对象,省去了var that=this的麻烦,耶耶耶~~~
接下来我们来总结一下,在ES5中:
this的值通常是由当前函数的执行环境所决定;
在全局作用域,this指向全局对象 (window对象);
当使用new关键字声明,this指向新建对象;
我们可以使用call(), bind(), apply()来设置this;
箭头函数不会绑定this
bind的模拟实现
bind 函数的两个特点:
1. 返回一个函数
2. 可以传入参数
Function.prototype.bind2 = function(context){
var that = this;
return function (){
that.apply(context)
}
}
var foo = {value:1}
var f = function(){
console.log(this.value)
}
f.bind2(foo)();//1
call的模拟实现
1. 将函数设为对象的属性
2. 执行该函数
3. 删除该函数
参考:https://blog.csdn.net/daimomo000/article/details/72897008
对比:
非箭头函数:
function fo() {
setTimeout(function() {
console.log(‘id:’, this.id);
}, 100);
}
var id = 21;
fo.call({ id: 42 });
// id: 21
箭头函数:
function foo() {
setTimeout(() => {
console.log(‘id:’, this.id);
}, 100);
}
var id = 21;
foo.call({ id: 42 });
// id: 42
上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到 100 毫秒后。如果是普通函数,执行时this应该指向全局对象window,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42}),所以输出的是42。
箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。
上代码
<script type="text/javascript">
//定义一个人类
function Person(name,age){
this.name=name;
this.age=age
}
//定义一个学生
function Student(name,age,grade){
Person.apply(this,arguments)//定义时,this指Student, arguments打出来是["Li", 11, "一班", callee: ƒ, Symbol(Symbol.iterator): ƒ]
this.grade=grade
}
var s=new Student("Li",11,"一班")
console.log(s);//{name: "Li", age: 11, grade: "一班"}
</script>
分析
Person.apply(this,arguments)等同于
Person.call(this,name,age)
如果说Person和Student的参数顺序不一样,必须用call了
<script type="text/javascript">
//定义一个人类
function Person(n,a){
this.n=n;
this.a=a
}
//定义一个学生
function Student(age,name,grade){
Person.call(this,age,name)
console.log("1",this)//1 Student {n: "Li", a: 11}
this.grade=grade
}
var s=new Student("Li",11,"一班")
console.log(s);//Student {n: "Li", a: 11, grade: "一班"}
</script>
应用:
1.apply可以将数组转化为一个参数接一个参数
Math.max(param1,param2,param3…)
Math.max(1,3,5,2)
//5
数组的话
Math.max([1,3,5,2])
//NaN
得
Math.max.apply(null,[1,3,5,2])
5
上面是ES5的写法
ES6的话,直接用扩展运算符…,将数据组转化为参数序列:
Math.max(...[1,3,5,2])
//5