想法来源
学习ES6视频时,看到老师的举例,如下图所示:
PPT中的截图如下:
一开始其实误以为是函数调用换了位置,就自己尝试了一波,发现了更多的情况,便进行分析整理如下。
已知: 箭头函数不绑定this
关键字,箭头函数中的this
,指向的是函数定义位置的上下文this
第一种情况:const
+箭头函数
const
具有块级属性,必须先声明再使用,所以不考虑声明先后的问题
源码
//const+箭头函数
function fn() {
console.log(this);
return () => {
console.log(this)
}
}
const obj = { name: '张三' };
const resFn = fn.call(obj); // 壹
resFn(); //贰
// 输出结果为:
//{name: '张三'}
//{name: '张三'}
分析如下
- 壹:因为
call
方法让fn()
里的console.log(this)
中的this
指向obj
,即this
指向{ name: '张三' };
- 贰:相当于
fn.call(obj)()
就相当于调用了fn()
里的匿名函数。但是并没有传入值,所以根据箭头函数的属性,这里的this
指向与匿名函数外的this
一致,即{ name: '张三' };
第二种情况:var
+箭头函数
var
具有变量提升和函数提升
1. 先声明变量,再调用函数
源码
//var+箭头函数
var obj = { name: '张三' }
function fn() {
console.log(this);
return () => {
console.log(this)
}
}
// var obj = { name: '张三' }
var resFn = fn.call(obj); // 壹
resFn(); // 贰
// 输出结果为:
//{name: '张三'}
//{name: '张三'}
分析如下
- 壹:与上面一致。因为
call
方法让fn()
里的console.log(this)
中的this
指向obj
,即this
指向{ name: '张三' };
- 贰:与上面一致。相当于
fn.call(obj)()
就相当于调用了fn()
里的匿名函数。但是并没有传入值,所以根据箭头函数的属性,这里的this
指向与匿名函数外的this
一致,即{ name: '张三' };
2. 先调用函数,再声明变量
在
var
中,该操作不会报错,故考虑此情况
源码
//var+箭头函数
var resFn = fn.call(obj);
function fn() {
console.log(this);
return () => {
console.log(this)
}
}
var obj = { name: '张三' };
// var resFn = fn.call(obj);
resFn();
//输出结果为:
//Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
//Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
分析如下
//var+箭头函数
// 实际执行如下
var resFn
var obj
function fn() {
console.log(this);
return () => {
console.log(this)
}
}
resFn = fn.call(obj); // 这时候obj还没有赋值,指向的就是window
obj = { name: '张三' };
resFn(); // 没有传入obj,箭头函数的this指向的就是上下文中的this,就是window
第三种情况:var
+普通函数
该方法作为对比项
1. 先声明变量,再调用函数
源码
// var + 普通函数
var obj = { name: '张三' }
function fn() {
console.log(this);
return function () {
console.log(this)
}
}
// var obj = { name: '张三' }
var resFn = fn.call(obj);
resFn();
// 输出结果:
//{name: '张三'}
//Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
分析如下
// var + 普通函数
// 实际执行如下
var obj
var resFn
function fn() {
console.log(this);
return function () {
console.log(this)
}
}
obj = { name: '张三' }
resFn = fn.call(obj); // fn()中的this指向obj,即{ name: '张三' }
resFn();
// resFn()相当于fn.call(obj)()调用了fn()中的匿名函数,
// 此时匿名函数中的this指向window
this
都指向obj
的方法
// var + 普通函数
var obj = { name: '张三' }
function fn() {
console.log(this);
return function () {
console.log(this)
}
}
// var obj = { name: '张三' }
var resFn = fn.call(obj);
resFn.call(obj);
// 输出结果:
//{name: '张三'}
//{name: '张三'}
2. 先调用函数,再声明变量
考虑此情况的理由同上
源码
// var + 普通函数
var resFn = fn.call(obj);
var obj = { name: '张三' };
function fn() {
console.log(this);
return function () {
console.log(this)
}
}
// var obj = { name: '张三' }
// var resFn = fn.call(obj);
resFn();
//输出结果:
//Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
//Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
分析如下
// var + 普通函数
// 实际执行如下
var resFn
var obj
function fn() {
console.log(this);
return function () {
console.log(this)
}
}
resFn = fn.call(obj); // obj尚未赋值,故 this 指向 window
obj = { name: '张三' };
resFn(); // fn.call(obj)(),调用匿名函数,指向window
第四种情况:const
+普通函数
我是附录内容啦啦啦啦啦……
此项作为对比项。因为
const
必须先声明再调用,所以不考虑先后问题。
源码
// const+普通函数
function fn() {
console.log(this);
return function () {
console.log(this)
}
}
const obj = { name: '张三' };
const resFn = fn.call(obj); // 1
resFn(); // 2
// 输出结果:
// {name: '张三'}
//Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
分析如下
- 1:
call()
方法使fn()
下的this
指向obj
- 2:
fn.call(obj)()
调用匿名函数,所以this
指向window
总结
普通函数中的this
指向
先弄明白普通函数中的
this
指向
源码
function fn() {
console.log('我是外面的' + this);
return function () {
console.log('我是里面的' + this)
}
}
fn.call()(); // 这一步其实相当于先调用了fn(),再调用里面匿名函数
// 输出结果
// 我是外面的[object Window]
// 我是里面的[object Window]
结论:
普通函数(两种声明方式:自定义函数,函数表达式)中的this
均指向window
函数中的方法调用,那么this
就指向调用者
const
/let
声明
因为
const
只能先声明再调用,所以无需考虑先后问题
fn()
里return
普通函数
内容详情请见“第四种情况”
结论:
fn()
下的this
指向call()
中指向的对象return
的匿名函数中的this
指向window
fn()
里return
箭头函数
内容详情请见“第一种情况”
结论:
fn()
下的this
指向call()
中指向的对象return
的箭头函数不绑定this
,其this
指向上下文中的this
,即与fn()
下的一致
var
声明
因为具有变量提升和函数提升,所以有多重情况可考虑
fn()
里return
普通函数
先声明变量再调用
内容详情请见“第三种情况”
结论:
fn()
下的this
指向call()
中指向的对象return
的匿名函数中的this
指向window
先调用再声明变量
内容详情请见“第三种情况”
结论:
- 两个
this
都指向window
fn()
里return
箭头函数
先声明变量再调用
内容详情请见“第二种情况”
结论:
- 两个
this
都指向call()
中指向的对象
先调用再声明变量
内容详情请见“第二种情况”
结论:
- 两个
this
都指向window