前言
this在使用的过程中起着至关重要的作用,弄懂this的指向也非常关键,本文介绍一些常见的this指向和一些与this相关的api,让你轻轻松松弄懂this指向
普通函数this
this的指向:我们可以大致的认为函数的this指向父级(上一级)。怎么说呢,看下面案例
- 当被定义为函数时,我们默认它指向window,为啥不说父级呢,我们看下面例子
let a = function (){
console.log(this.a) //this->window
}
a() //undefined
var a = function (){
console.log(this.a) //this->window
}
a() // F()
为啥同样是定义函数,let得到的结果是undefined,而var得到的才是我们想要的结果呢?
在浏览器环境中系统默认生成window(顶层对象)里面来存放var声明的全局变量, 而let声明的全局变量不属于顶层对象的属性,var定义的元素是直接添加在window上的,let定义的元素不在顶层对象上,所以let定义的函数a在window上找不到。所以会出现undefined.
- 当被作为属性函数定义的时候,指向调用的父级元素。怎么说呢,看下面案例
var c =2
var a = {
c:1,
b: function () {
console.log(this.c) //this->a
}
}
a.b() //输出 1
我们能清楚的看到属性函数b的父级为a,所以this指向a
- 当属性函数赋值给函数时
var c =2
var a = {
c:1,
b: function () {
console.log(this.c) // this->a
}
}
let f = a.b
f() //输出1
其实此函数就是跟例一的情况是一样的,相当于
var c = 1
let f = function () {
console.log(this.c) //输出1
}
不用多讲参考例一
箭头函数this
this指向:指向父级函数的this指向(上两级)
官方介绍
- 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
- this对象的指向是可变的,但是在箭头函数中,它是固定的。
- 箭头函数根本没有自己的this
- 箭头函数里面根本没有自己的this,而是引用外层的this。
具体参考阮一峰es6入门阮一峰es6入门
- 谁调用指向谁的this也相当于指向父级函数的this,例如
var a = ()=>{
console.log(this) //this->window
}
a() //window
var a = {
b: ()=> {
console.log(this) //window
}
}
a.b() //window
var a = {
c:1,
b: {
d: ()=> {
console.log(this) //window
}
d()
}
}
a.b.d() //window
var a = {
c:1,
b: function() {
d =()=> {
this.c++ //this->a
}
}
}
a.b()
console.log(c) //输出2
我们知道箭头函数是指向父级函数的this,前面几个没有父级函数就指向window,箭头函数的父级函数为b,b的this指向a。所以箭头函数指向a。也可以这样理解箭头函数的父级(上级)为b,b的父级(上级)为a,所以箭头函数的this指向a。
this指向相当于如下代码
var a = {
c:1,
b: function() {
this.c++ //this->a
}
}
a.b()
console.log(c)
看起来似乎有点多此一举,但是当配合一些dom操作的时候会有用处例如:
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000); //this->Timer
// 普通函数
setInterval(function () {
this.s2++; //this->setInterval
}, 1000);
}
此时箭头函数起了作用而匿名函数并没有起到作用
使用api时this
与函数this相关的api,可以直接改变this
- bind
- apply
- call
这三个api都能改变函数的this指向。以下foo为定义号的函数
- bind
-
使用方法 foo.bind(a,b,c)
第一个参数a为函数调用的时候指定的this指向,this指向a 例如foo.bind(window,b,c)指向window 后面两个数b,c为形参,有的时候加,没有的话可以不写 此api只是改变了函数的this指向,并没有直接执行函数,而另外两个api即改变函数this指向又执行了函数
- apply
-
使用方法foo.apply(a,[b,c])
第一个参数a为函数调用的时候指定的this指向,this指向a 例如foo.apply(window,[b,c])指向window 后面两个数b,c为形参,有的时候加,没有的话可以不写 此api只是改变了函数的this指向,并且执行函数
- call
-
使用方法foo.call(a,b,c)
第一个参数a为函数调用的时候指定的this指向,this指向a 例如foo.call(window,b,c)指向window 后面两个数b,c为形参,有的时候加,没有的话可以不写 此api只是改变了函数的this指向,并且执行函数
总结
本文讲解了this的指向问题
- 普通函数this基本指向父级(上一级)
- 箭头函数this基本指向父级函数的this指向(上两级)
- api可以直接改变你想要指向的this
以上为本人对this的见解,如有问题请及时提出。大家一起讨论研究