一篇文章详细讲解JavaScript中的this(普通函数、箭头函数、 函数运用)
前言
this对象:解析器在每次调用函数时,都会向函数内部转递一个隐含的参数,这个参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象,根据函数调用方式的不同,this会指向不同的对象
一、将根据一下几个方面介绍this的指向问题
- 全局环境中的 this
- 函数中的 this
- 对象方法中的 this
- 构造函数中的 this
- 事件处理函数中的 this
- 箭头函数中的 this
1、全局环境中的this
在全局环境中(不在任何函数或对象内部),this指向全局对象(在浏览器环境中是window,在node.js中是global)
2、函数中的this
当一个函数被直接调用时,this在非严格模式下指向全局对象(window),在严格模式下指向undefined
JS严格模式:JavaScript在语法和行为上存在一些模糊的特性,可能导致一些不易察觉的错误,为提高代码的质量和可维护性,js引入了严格模式,通过启用一些额外的规则,强制执行更严格的语法和行为。在严格模式下代码中的潜在问题将被捕获并抛出错误,有助于提前发现和修复潜在bug。
3、对象方法中的this
当函数作为对象的方法被调用时,this指向调用该方法的对象
4、构造函数中的this
使用new关键字(实例化)调用函数时,该函数被当作构造函数(类),this会指向新创建的对象实例
构造函数怎么执行创建对象的过程:
- 调用一个构造函数,他会立即创建一个对象
- 将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象
- 逐行执行函数中的代码
- 将新建的对象作为返回值返回
在构造函数中,创建对象和返回对象都给我们隐藏了,使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。我们将通过一个构造函数创建的对象,称为是该类的实例。
5、事件处理函数中的this
在DOM事件处理函数中,this通常指向触发事件的元素。
7、箭头函数中的this
箭头函数没有自己的this,它的this继承自外层作用域的this
二、改变this指向的方法
由于箭头函数的this来自于继承,箭头函数无法使用以下三种方法改变this指向
1、call()方法
call
方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向- 语法: 函数名.call(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...)
- 使用 call 方法的时候:
1、会立即执行函数
2、第一个参数是你要改变的函数内部的 this 指向
3、第二个参数开始,依次是向函数传递参数
fn(1,2)
的时候,函数内部的 this 指向 window(函数被直接调用)fn.call(obj, 1, 2)
的时候,函数内部的 this 就指向了 obj 这个对象
2、apply()方法
apply
方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向- 语法: 函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...])
- 使用 call 方法的时候:
1、会立即执行函数
2、第一个参数是你要改变的函数内部的 this 指向
3、第二个参数是一个 数组,数组里面的每一项依次是向函数传递的参数(和call方法的主要区别点)
fn(1,2)
的时候,函数内部的 this 指向 window(函数被直接调用)fn.call(obj, 1, 2)
的时候,函数内部的 this 就指向了 obj 这个对象
3、bind()方法
bind
方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向- 和 call / apply 有一些不一样,就是不会立即执行函数,而是返回一个已经改变了 this 指向的函数
- 语法: var newFn = 函数名.bind(要改变的 this 指向); newFn(传递参数)
- bind 调用的时候,不会执行 fn 这个函数,而是返回一个新的函数
- 这个新的函数就是一个改变了 this 指向以后的 fn 函数
fn(1, 2)
的时候 this 指向 windownewFn(1, 2)
的时候执行的是一个和 fn 一摸一样的函数,只不过里面的 this 指向改成了 obj
三、回调函数中this指向
这里我们补充一下在回调函数运用中this指向(也是容易混淆的知识点)
1、对象方法作为回调函数
如果回调函数是一个对象的方法,并且是以对象方法的方式传递进去的,那么 this 通常会指向该对象。
在这个例子中,forEach 是数组的方法,myObject.callbackFunction 作为回调函数传递给 forEach。当 forEach 调用这个回调函数时,this 仍然指向 myObject,因为这个函数本质上还是 myObject 的一个方法。
2、箭头函数作为回调函数
箭头函数没有自己的 this,它会继承外层作用域的 this(依据词法作用域规则)。
根据上面两个例子,这里我们介绍一下普通函数和箭头函数在确定this指向时的一些区别:
1、普通函数
普通函数在函数定义时会确定函数的作用域,但不会明确函数中this的指向。普通函数中this的指向是在函数被调用时被确定(指向调用者或者全局对象)
2、箭头函数
箭头函数由于其本身不会生成this,其this继承自外层作用域。箭头函数在定义时不仅会确定作用域,而且会捕获外层作用域的this作为自身的this,箭头函数的this在定义时就已经确定,在其后的函数调用时,无论调用箭头函数的是谁它的this指向都不会发生改变。
以上面这个例子为例:
箭头函数定义在 outerFunction 这个函数内部,注意不是定义在 forEach 方法内。具体可以了解一下函数传参的步骤,这里箭头函数是先在 outerFunction 这个函数内部定义,之后才作为参数传给 forEach 方法。箭头函数继承了 outerFunction 函数的this,并在之后被 forEach 方法调用时不会发生改变。
3、回调函数指向全局对象的常见情况
当普通函数作为回调函数,并且这个普通函数是被一个全局函数(如 setTimeout、setInterval)或者在全局作用域中独立调用的函数(没有通过对象来调用)调用时,在非严格模式下,this 通常会指向全局对象。
四、总结与常见错误示例
this指向:1、普通函数:谁调用函数,this就指向谁,没有调用者就指向全局对象Window
2、箭头函数:箭头函数不会创建this,它的this继承自上层作用域中的this
1、案例一
此处的function为普通函数,被一个全局函数调用,其this指向全局对象 Window 。
要想输出 Eve ,将此处的普通函数改为箭头函数即可。
2、案例二
nestedFunction 是作为 inner 对象的方法被调用,this指向 inner 对象(根据普通函数 this 指向的规则,当函数作为对象的方法被调用时,this 会指向调用该函数的对象。)
4.2.1、使用外层作用域this的方法
想要访问到 outer 对象的 name 属性,可以使用以下两种方法:
1、保存外层 this 的引用
在方法的开头先把 this 保存到一个变量中(通常命名为 self 或 that 等),然后在 inner 对象中使用这个保存的变量来访问 outer 对象的属性。
2、使用箭头函数
将 nestedFunction 改为箭头函数,因为箭头函数会继承外层作用域的 this,在这里外层作用域是 outer.innerFunction(),其 this 指向 outer 对象,所以箭头函数里的 this 也能指向 outer 对象。
总结
上一篇:JavaScript中实现Sleep功能及其应用的几种方法
栏 目:JavaScript
下一篇:Vue 3 中 vue-router 的 router.resolve () API详解
本文标题:一篇文章详细讲解JavaScript中的this(普通函数、箭头函数、 函数运用)
本文地址:https://fushidao.cc/wangluobiancheng/23719.html
您可能感兴趣的文章
- 07-21Webpack打包速度优化方案汇总
- 07-21Vuex Actions多参数传递的解决方案
- 07-21前端JavaScript数组方法总结(非常详细!)
- 07-21使用Node.js制作图片上传服务的详细教程
- 07-21vue3整合SpringSecurity加JWT实现权限校验
- 07-21vue3中pinia的使用及持久化的实现
- 07-21vue3整合SpringSecurity加JWT实现登录认证
- 07-21一文详解如何将Javascript打包成exe可执行文件
- 07-21JavaScript中if、else if、else和switch的语法、用法及注意事项
- 07-21Vue 3 中 vue-router 的 router.resolve () API详解


阅读排行
- 1Webpack打包速度优化方案汇总
- 2Vuex Actions多参数传递的解决方案
- 3前端JavaScript数组方法总结(非常详细!)
- 4使用Node.js制作图片上传服务的详细教程
- 5vue3整合SpringSecurity加JWT实现权限校验
- 6vue3中pinia的使用及持久化的实现
- 7vue3整合SpringSecurity加JWT实现登录认证
- 8一文详解如何将Javascript打包成exe可执行文件
- 9JavaScript中if、else if、else和switch的语法、用法及注意事项
- 10Vue 3 中 vue-router 的 router.resolve () API详解
推荐教程
- 04-23JavaScript Array实例方法flat的实现
- 04-23Vue3使用v-if指令进行条件渲染的实例代码
- 04-23THREE.JS使用TransformControls对模型拖拽的代码实例
- 07-21JavaScript判断数据类型的四种方式总结
- 04-23vue3+ts项目搭建的实现示例
- 07-21JavaScript检查变量类型的常用方法
- 07-21基于vue3与supabase系统认证机制详解
- 07-21JavaScript双问号操作符(??)的惊人用法总结大全
- 07-21JavaScript中if、else if、else和switch的语法、用法及注意事项
- 07-21Vue中使用vue-plugin-hiprint插件进行打印的功能实现