返回顶部
首页 > 资讯 > 前端开发 > JavaScript >详解JavaScript什么情况下不建议使用箭头函数
  • 334
分享到

详解JavaScript什么情况下不建议使用箭头函数

2024-04-02 19:04:59 334人浏览 八月长安
摘要

目录this指向原理问题的由来内存的数据结构函数环境变量箭头函数的缺点不适用的场景总结箭头函数作为es6新增的语法,在使用时不仅能使得代码更加简洁,而且在某些场景避免this指向问题

箭头函数作为es6新增的语法,在使用时不仅能使得代码更加简洁,而且在某些场景避免this指向问题。但是箭头函数不是万能的,也有自己的缺点以及不适用的场景,虽然可以解决this只想问题,但是也可能会带来this指向问题。具体场景具体分析,本文就深入探讨箭头函数。

箭头函数没有自己的this,其this取决于上下文中定义的this。

this指向原理

问题的由来

学懂 javascript 语言,一个标志就是理解下面两种写法,可能有不一样的结果。

var obj = {
  foo: function () {}
};

var foo = obj.foo;

// 写法一
obj.foo()

// 写法二
foo()

上面代码中,虽然obj.foofoo指向同一个函数,但是执行结果可能不一样。请看下面的例子。

var obj = {
  foo: function () { console.log(this.bar) },
  bar: 1
};

var foo = obj.foo;
var bar = 2;

obj.foo() // 1
foo() // 2

这种差异的原因,就在于函数体内部使用了this关键字。很多教科书会告诉你,this指的是函数运行时所在的环境。对于obj.foo()来说,foo运行在obj环境,所以this指向obj;对于foo()来说,foo运行在全局环境,所以this指向全局环境。所以,两者的运行结果不一样。

这种解释没错,但是教科书往往不告诉你,为什么会这样?也就是说,函数的运行环境到底是怎么决定的?举例来说,为什么obj.foo()就是在obj环境执行,而一旦var foo = obj.foofoo()就变成在全局环境执行?

本文就来解释 JavaScript 这样处理的原理。理解了这一点,你就会彻底理解this的作用。

内存的数据结构

JavaScript 语言之所以有this的设计,跟内存里面的数据结构有关系。

var obj = { foo:  5 };

上面的代码将一个对象赋值给变量obj。JavaScript 引擎会先在内存里面,生成一个对象{ foo: 5 },然后把这个对象的内存地址赋值给变量obj

也就是说,变量obj是一个地址(reference)。后面如果要读取obj.foo,引擎先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的foo属性。

原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。举例来说,上面例子的foo属性,实际上是以下面的形式保存的。

{
  foo: {
    [[value]]: 5
    [[writable]]: true
    [[enumerable]]: true
    [[configurable]]: true
  }
}

注意,foo属性的值保存在属性描述对象的value属性里面。

函数

这样的结构是很清晰的,问题在于属性的值可能是一个函数。

var obj = { foo: function () {} };

这时,引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。

{
  foo: {
    [[value]]: 函数的地址
    ...
  }
}

由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行。

var f = function () {};
var obj = { f: f };

// 单独执行
f()

// obj 环境执行
obj.f()

环境变量

JavaScript 允许在函数体内部,引用当前环境的其他变量。

var f = function () {
  console.log(x);
};

上面代码中,函数体里面使用了变量x。该变量由运行环境提供。

现在问题就来了,由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。

var f = function () {
  console.log(this.x);
}

上面代码中,函数体里面的this.x就是指当前运行环境的x

var f = function () {
  console.log(this.x);
}

var x = 1;
var obj = {
  f: f,
  x: 2,
};

// 单独执行
f() // 1

// obj 环境执行
obj.f() // 2

上面代码中,函数f在全局环境执行,this.x指向全局环境的x

obj环境执行,this.x指向obj.x

回到本文开头提出的问题,obj.foo()是通过obj找到foo,所以就是在obj环境执行。一旦var foo = obj.foo,变量foo就直接指向函数本身,所以foo()就变成在全局环境执行。

箭头函数的缺点

1.箭头函数没有arguments参数列表,普通函数可以直接获取到

arguments是调用函数时,传递给函数的一个类似数组的对象,几乎所有的函数都有此局部变量,可直接访问并使用传递给函数的参数列表,箭头函数除外。该变量不是数组对象,只是类似于数组,没有数组的常用方法。

let fn1 = () => {
    console.log('arguments', arguments);
}
fn1(1, 2); // arguments is not defined
let fn2 = function() {
    console.log('arguments', arguments);
}
fn2(1, 2); // Arguments对象,可查看具体的参数

2.无法通过apply、call、bind改变this的指向。箭头函数的this默认指向父作用域或者当前调用对象,无法通过call等修改,但是function申明的函数可以修改this

this指向是js中经常容易出错的地方。箭头函数的this指向是固定的,一般都是指向父作用域,默认指向window,不能在apply、call、bind中改变this的指向。普通函数的this指向不是固定的,有可能根据传入的对象改变。

console.log('this1', this); // 指向window
let fn3 = () => {
    console.log('this2', this); // 指向window
}
fn3.call({x: 'y'}); // 传入新的对象
// fn3.apply({x: 'y'});
let fn4 = function() {
    console.log('this3', this); // 指向{x: 'y'}
}
fn4.call({x: 'y'});

不适用的场景

1.对象的方法,不建议使用箭头函数

let obj = {
    key: 'key',
    geTKEy: () => {
        return this.key;
    },
    getKey2() {
        return this.key;
    }
};
obj.getKey(); // this指向window,返回值取决于window中是否有对应的属性
obj.getKey2(); // this指向obj,返回 'key'

2.对象的原型的方法,不建议使用箭头函数

每个对象都有原型,原型也是一个对象,因此也不能添加箭头函数的方法

let obj = {
    key: 'key'
};
obj.__proto__.getKey = () => {
    console.log('this', this); // this指向window
    return this.key;
}
obj.getKey();

3.箭头函数不能用作构造函数

定义一个构造函数可通过函数定义或者使用class定义一个类。箭头函数不能用作构造函数,可使用普通函数

let fn5 = (userName, passwd) => {
    this.userName = userName;
    this.passwd = passwd;
}
let f1 = new fn5('张三', '123'); // fn5 is not a constructor
console.log(f1.userName);
let fn6 = function (userName, passwd) {
    this.userName = userName;
    this.passwd = passwd;
}
let f2 = new fn6('张三', '123');
console.log(f2.userName); // 张三

4.监听事件中需要使用this时不建议使用箭头函数

比如在addEventListener中,如果要在回调函数中使用this,那么就不建议使用箭头函数,而是应该普通函数,更好的是使用已定义的函数名,便于回收事件监听,避免可能的内存泄漏。

dom.addEventListener('click', () => {
    console.log('this', this); // this指向window
})

5.Vue的生命周期以及methods中的方法不建议使用箭头函数

页面中创建的Vue实例,本质上来说也就是一个对象,其生命周期就是对应的属性,methods也是一个对象。在Vue的生命周期或者methods中使用箭头函数,则this的指向将不是当前Vue实例,而是window对象,如果在方法中使用了this,则可能会抛出错误。

export default {
    mounted() {},
    // mounted: () => {}
    methods: {
        getKey() {},
        // getKey: () => {}
    }
}

总结

  • 箭头函数有优点,也有缺点,不可盲目使用,一定要清楚的知道为什么要使用箭头函数,为什么不能使用箭头函数
  • 箭头函数可解决this指向,也可能带来this指向问题

到此这篇关于详解JavaScript什么情况下不建议使用箭头函数的文章就介绍到这了,更多相关JavaScript箭头函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 详解JavaScript什么情况下不建议使用箭头函数

本文链接: https://lsjlt.com/news/152461.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详解JavaScript什么情况下不建议使用箭头函数
    目录this指向原理问题的由来内存的数据结构函数环境变量箭头函数的缺点不适用的场景总结箭头函数作为ES6新增的语法,在使用时不仅能使得代码更加简洁,而且在某些场景避免this指向问题...
    99+
    2024-04-02
  • js中不能使用箭头函数的情况是什么
    这篇文章主要介绍“js中不能使用箭头函数的情况是什么”,在日常操作中,相信很多人在js中不能使用箭头函数的情况是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”js中不能使用箭头函数的情况是什么”的疑惑有所...
    99+
    2023-07-02
  • JS中不应该使用箭头函数的四种情况详解
    目录箭头函数的一些缺点1、不支持参数对象2、无法通过apply、call、bind来改变this指针什么时候不能使用箭头功能1、请不要在构造函数中使用箭头函数2、请不要在点击事件中操...
    99+
    2024-04-02
  • 详解JavaScript中的箭头函数的使用
    目录前言箭头函数语法无圆括号语法隐式返回注意隐式返回错误无法命名箭头函数如何处理this关键字匿名箭头函数不正常工作的情况箭头函数作为对象方法箭头函数与第三方库箭头函数没有argum...
    99+
    2022-11-13
    JavaScript箭头函数使用 JavaScript 箭头函数 JS 箭头函数
  • JavaScript哪些场景不能使用箭头函数
    目录1. 定义对象方法 2.定义原型方法 3. 定义事件回调函数 4. 定义构造函数 1. 定义对象方法    JS 中对象方法的定义方式是在对象上定义一个指向函数的属性...
    99+
    2024-04-02
  • JavaScript箭头函数的this怎么使用
    这篇文章主要介绍“JavaScript箭头函数的this怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JavaScript箭头函数的this怎么使用”文章能...
    99+
    2024-04-02
  • js中什么时候不能使用箭头函数
    目录箭头函数箭头函数有什么缺点?什么时候不能使用箭头函数?1. 对象方法中,不适用箭头函数为什么对象方法中,箭头函数的this指向不是这个对象?2. 原型方法中,不适用箭头函数3. ...
    99+
    2024-04-02
  • es6箭头函数什么时候不能用
    这篇文章主要讲解了“es6箭头函数什么时候不能用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“es6箭头函数什么时候不能用”吧! ...
    99+
    2024-04-02
  • JavaScript箭头函数与剩余参数怎么使用
    本篇内容主要讲解“JavaScript箭头函数与剩余参数怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript...
    99+
    2024-04-02
  • 什么情况下不能使用Java泛型
    这篇文章主要讲解了“什么情况下不能使用Java泛型”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“什么情况下不能使用Java泛型”吧!1. 前言Java 1.5 引入了泛型来保证类型...
    99+
    2023-06-02
  • 什么情况下使用 Golang 函数类型更合适?
    在 golang 中使用函数类型的情况有:传递函数作为参数创建回调抽象化行为 何时在 Golang 中使用函数类型 在 Golang 中,函数类型用于表示可以作为函数调用的值。这在以下...
    99+
    2024-04-19
    golang 函数类型
  • 如何解析vue data不可以使用箭头函数问题
    这篇文章将为大家详细讲解有关如何解析vue data不可以使用箭头函数问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。首先需要明确,a() {}和 b: () =>...
    99+
    2024-04-02
  • JS箭头函数的语法是什么及怎么使用
    本篇内容介绍了“JS箭头函数的语法是什么及怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!JavaScript的箭头函数随着ECMAS...
    99+
    2023-07-04
  • 不使用他人jar包情况下优雅的进行dubbo调用详解
    目录1、正常dubbo调用流程2、如果想在不引用他人jar包的情况下如何调用呢?dubbo泛化调用-dubbo原生支持的优雅方法使用场景:如何使用:实现原理:3、总结1、正常dubb...
    99+
    2024-04-02
  • MySQL数据库中什么情况下需要使用索引
    这篇文章主要介绍MySQL数据库中什么情况下需要使用索引,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!什么情况下需要使用索引(1)列经常被用于where条件中(2)列中有大...
    99+
    2024-04-02
  • PHP Switch语句的使用技巧:不使用Break的情况下会发生什么?
    PHP中的Switch语句是一种常用的条件语句,通常用于根据不同情况执行不同的代码块。在Switch语句中,每个case后面会跟一个代码块,并且通常会在代码块末尾使用break关键字来...
    99+
    2024-04-02
  • 在不使用ssr的情况下怎么解决Vue单页面SEO问题
    小编给大家分享一下在不使用ssr的情况下怎么解决Vue单页面SEO问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!只是用php...
    99+
    2024-04-02
  • 如何为通用函数创建别名以避免“在未实例化的情况下使用通用函数”错误?
    知识点掌握了,还需要不断练习才能熟练运用。下面编程网给大家带来一个Golang开发实战,手把手教大家学习《如何为通用函数创建别名以避免“在未实例化的情况下使用通用函数”错误?》,在实现功能的过程中也...
    99+
    2024-04-04
  • javascript图片在下载时被用户中断使用什么函数,详细讲解
    这篇文章将为大家详细讲解有关javascript图片在下载时被用户中断使用什么函数,详细讲解,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。用户中断图片下载时的 JavaScript 函数 在 JavaSc...
    99+
    2024-04-02
  • javascript按下鼠标时触发此事件使用什么函数,详细讲解
    这篇文章将为大家详细讲解有关javascript按下鼠标时触发此事件使用什么函数,详细讲解,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。按下鼠标时触发事件的 JavaScript 函数 当用户按下鼠标时,...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作