## 普通函数在不同的执行环境下,this指向
this是什么,是和执行上下文绑定的,也就是说每个执行上下文中都有一个 this。
### 1、在全局中,指向window
``` js
// 普通函数
function fn(){
console.log(this)
}
fn() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
```
``` js
// 箭头函数
var fn = ()=>{
console.log(this)
}
fn() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
```
在全局中,指向就没有什么可说的,都是window对象
### 2、普通对象下的函数,不同的执行环境
#### 2.1当普通函数被普通对象的属性(方法)调用
``` js
// 普通函数
var obj = {
a: 123,
fn: function(){
console.log(this)
}
}
var obj2 = obj.fn
obj2() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
obj.fn() // {a: 123, fn: ƒ}
```
``` js
// 箭头函数
var obj = {
a: 123,
fn: () => {
console.log(this)
}
}
var obj2 = obj.fn
obj2() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
obj.fn() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
```
当普通函数被普通对象的属性(方法)调用,则this执行这个普通对象obj;
当箭头函数被普通对象的属性(方法)调用,则this指向window对象。
#### 2.2 注意高阶函数,先后执行的环境有所变化时,this执行跟随变化
注:可通过abc进行改变指向(apply、bind、call)
```
var a = 'window'
var obj = {
a: 123,
fn:function(){
console.log('fn的this:',this,this.a)
return function(){
console.log('匿名:',this,this.a)
}
},
cn:function (){
return ()=>{
console.log('匿名箭头:',this,this.a)
}
}
}
var obj_fn = obj.fn
var obj_cn = obj.cn
obj_fn()() // 结果如下图
obj_cn()()
obj.fn()()
obj.cn()()
```
![](https://img.kancloud.cn/9b/77/9b77184655a529708589b338938f65e3_921x190.png)
#### 2.3定义_that指向fn的this
```
// 普通函数
var a = 'window'
var obj = {
a: 123,
fn:function(){
var _that = this
console.log('fn的this:',this,',this.a:',this.a)
return function(){
console.log('匿名:',',this: ',this,',_that: ',_that)
}
}
}
var obj2 = obj.fn
obj2()()
obj.fn()()
```
![](https://img.kancloud.cn/c8/c9/c8c9840af084048c1e84d834a9df6e0f_1529x124.png)
``` js
// 箭头函数
var a = 'window'
var obj = {
a: 123,
fn:function(){
var _that = this
console.log('fn的this:',this,',this.a:',this.a)
return ()=>{
console.log('匿名:',',this: ',this,',_that: ',_that)
}
}
}
var obj2 = obj.fn
obj2()()
obj.fn()() // _that在这里最容易犯错了
```
![](https://img.kancloud.cn/47/4c/474cb0eee1b8ac69f532c92119b69871_1525x119.png)
#### 2.4全局变量累计
```js
var a = 1;
window.b = 2
var obj = {
a: 2,
b: 4,
ab:function(){ // 此处换成箭头函数,会怎么样呢?
this.a+=5;
a+=8
this.b+=5
b+=8
console.log(a,b,this.a,this.b,'a-----b')
}
}
obj.ab(); // 9 10 7 9 "a-----b"
console.log('ab:',a,b,this.a,this.b) // ab: 9 10 9 10
var fn = obj.ab;
fn() // 22 23 22 23 "a-----b"
console.log('ab-fn:',a,b,this.a,this.b) // ab-fn: 22 23 22 23
```
分析:
1、`obj.ab(); `时,a和this.a区别就是一个全局window.a(既var a),一个普通对象obj.a(this.a);
2、`console.log('ab:',a,b,this.a,this.b) `时,可通过window===this、window.a=a理解,故都是a===this.a理解,记住此时a=9、b=10;
3、`var fn = obj.ab;fn() `时,*fn执行环境时window*,那此时this.a等于什么呢?又等于什么呢?可以这样理解window.a=this.a=a,故a=9+5+8,b=10+5+8
ab函数换成箭头函数,则函数内:`var a = window.a=this.a`了。
#### 2.5内层函数不会继承上层函数this
```
var obj = {
ab:function(){
console.log('ab:',this)
function fn(){
console.log('fn:',this)
}
fn()
}
}
obj.ab() // 结果图下 fn 不会继承ab()的this
var out = obj.ab
out()
```
![](https://img.kancloud.cn/66/61/6661b076c6b688e7c1da38a9a9f9b5d1_682x122.png)
### 总结:
普通函数this指向,取决于调用时的环境在哪里;
箭头函数this指向,取决于父级上下文环境在哪里;
注:箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数。
- 首页
- 2021年
- 基础知识
- 同源策略
- 跨域
- css
- less
- scss
- reset
- 超出文本显示省略号
- 默认滚动条
- 清除浮动
- line-height与vertical-align
- box-sizing
- 动画
- 布局
- JavaScript
- 设计模式
- 深浅拷贝
- 排序
- canvas
- 防抖节流
- 获取屏幕/可视区域宽高
- 正则
- 重绘重排
- rem换算
- 手写算法
- apply、call和bind原理与实现
- this的理解-普通函数、箭头函数
- node
- nodejs
- express
- koa
- egg
- 基于nodeJS的全栈项目
- 小程序
- 常见问题
- ec-canvas之横竖屏切换重绘
- 公众号后台基本配置
- 小程序发布协议更新
- 小程序引入iconfont字体
- Uni-app
- 环境搭建
- 项目搭建
- 数据库
- MySQL数据库安装
- 数据库图形化界面常用命令行
- cmd命令行操作数据库
- Redis安装
- APP
- 控制缩放meta
- GIT
- 常用命令
- vsCode
- 常用插件
- Ajax
- axios-services
- 文章
- 如何让代码更加优雅
- 虚拟滚动
- 网站收藏
- 防抖节流之定时器清除问题
- 号称破解全网会员的脚本
- 资料笔记
- 资料笔记2
- 公司面试题
- 服务器相关
- 前端自动化部署-jenkins
- nginx.conf配置
- https添加证书
- shell基本命令
- 微型ssh-deploy前端部署插件
- webpack
- 深入理解loader
- 深入理解plugin
- webpack注意事项
- vite和webpack区别
- React
- react+antd搭建
- Vue
- vue-cli
- vue.config.js
- 面板分割左右拖动
- vvmily-admin-template
- v-if与v-for那个优先级高?
- 下载excel
- 导入excel
- Echart-China-Map
- vue-xlsx(解析excel)
- 给elementUI的el-table添加骨架
- cdn引入配置
- Vue2.x之defineProperty应用
- 彻底弄懂diff算法的key作用
- 复制模板内容
- 表格操作按钮太多
- element常用组件二次封装
- Vue3.x
- Vue3快速上手(第一天)
- Vue3.x快速上手(第二天)
- Vue3.x快速上手(第三天)
- vue3+element-plus搭建项目
- vue3
- 脚手架
- vvmily-cli
- TS
- ts笔记
- common
- Date
- utils
- axios封装
- 2022年
- HTML
- CSS基础
- JavaScript 基础
- 前端框架Vue
- 计算机网络
- 浏览器相关
- 性能优化
- js手写代码
- 前端安全
- 前端算法
- 前端构建与编译
- 操作系统
- Node.js
- 一些开放问题、智力题