做者:Michael Thiessen
译者:前端小智
来源:techalyst
点赞再看,养成习惯本文
GitHub
https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了不少个人文档,和教程资料。欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。javascript
当咱们使用 Vue 在愉快的开发项目的时候,忽然报了一个错误:前端
this is undefined
别担忧,不仅有你一我的,我也常常遇到这个问题不少次,接下咱们一块儿来看看如何解决这个问题。vue
一个可能的缘由是混淆了常规函数和箭头函数的用法,若是你遇到这个问题,我猜你用的是箭头函数。若是用常规函数替换箭头函数,它可能会为你修复这个问题。java
咱们再深刻一点,试着理解为何会这样。ios
毕竟,知识就是力量,若是知道形成问题的缘由,那么咱们未来能够避免不少挫败感和时间浪费。git
还有一些其它缘由可能也会出现此类错误。github
fetch
或 axios
获取数据lodash
或 underscore
这类的库在 JS 中,咱们有两种不一样的函数。它们以几乎相同的方式运做,除了它们处理变量的方式不一样。面试
这给新旧Javascript开发人员带来了不少困惑,可是当咱们弄懂这个问题时,就很好会有这个困惑。编程
常规函数能够用几种不一样的方式定义。axios
第一种方法在 Vue 组件中较不常见,由于写出来要更长一些:
methods: { regularFunction: function() { // Do some stuff } }
第二种方法是简写方式,咱们也常用:
methods: { shorthandFunction() { // Do some stuff } }
在像这样的常规函数中,this
将引用函数的“全部者”。由于咱们是在Vue组件上定义它的,因此this
指的是Vue组件。
在大多数状况下,咱们应该在 Vue 中使用常规函数,特别是在建立时
虽然常规函数一般是咱们所须要的,可是箭头函数也很是方便。
箭头函数能够更短,更快的编写,所以最近得到了普遍的欢迎。可是,它们在对象上定义方法时并无太大的不一样,就像咱们在编写Vue组件时所作的那样。
这是他们在Vue组件上的样子:
methods: { arrowFunction: () => { // Do some stuff } }
在处理 this
问题时,真正的差别开始发挥做用。
箭头函数采用词法做用域,意味着箭头函数从它的上下文中获取this
。
若是试图从Vue组件上的箭头函数内部访问 this
,将获得一个错误,由于 this
不存在
data() { return { text: 'This is a message', }; }, methods: { arrowFunction: () => { console.log(this.text); // ERROR! this is undefined } }
简而言之,尽可能避免在Vue组件上使用箭头函数。这将会省去许多头痛和困惑的问题。
有时使用箭头函数是很好的,但这只在不引用this
的状况下才有效。
computed: { location: () => window.location, }
如今咱们知道两种主要的函数类型,如何正确使用它们?
当咱们只须要建立一个函数而不须要从其余任何地方调用它时,匿名函数很是有用。
下面是使用匿名函数的一些场景
axios
或 fetch
访存数据filter
、map
和reduce
等函数方法来个例子看一下:
// Fetching data fetch('/getSomeData').then((data) => { this.data = data; }); // Functional methods const array = [1, 2, 3, 4, 5]; const filtered = array.filter(number => number > 3); const mapped = array.map(number => number * 2); const reduced = array.reduce((prev, next) => prev + next);
从示例中能够看到,大多数状况下,当咱们建立匿名函数时,使用箭头函数。咱们一般使用箭头函数有几个缘由
在Vue方法中,箭头函数也能够做为匿名函数使用。
等等,咱们不是刚发现当咱们试图访问 this
时,箭头函数不起做用吗?
这就是区别所在。
当咱们在常规函数或简写函数中使用箭头函数时,常规函数将this
设置为咱们的Vue组件,而箭头函数则不同。
来个例子:
data() { return { match: 'This is a message', }; }, computed: { filteredMessages(messages) { console.log(this); // Vue const filteredMessages = messages.filter( // 引用咱们的Vue组件 (message) => message.includes(this.match) ); return filteredMessages; } }
filter
方法能够访问this.match
,由于箭头函数使用的方法与filteredMessages
方法使用的上下文相同。 因为此方法是常规函数(而不是箭头函数),所以将其自身的上下文设置为Vue实例。
让咱们进一步讨论如何使用axios
或fetch
来获取数据。
若是正在使用fetch
或axios
获取异步数据,最好使用 Promise
。Promise
喜欢匿名箭头函数,它们也使处理this
问题变得容易得多。
若是你正在获取一些数据并想在你的组件上设置它,这是你应该作的正确的方式:
export default { data() { return { dataFromServer: undefined, }; }, methods: { fetchData() { fetch('/dataEndpoint') .then(data => { this.dataFromServer = data; }) .catch(err => console.error(err)); } } };
请注意,咱们如何在 Vue 组件上使用常规函数做为方法,而后在 Promise 内部使用匿名箭头函数
.then(data => { this.dataFromServer = data; })
在fetchData()
做用域内,咱们将this
设置为Vue组件,由于它是一个常规函数。因为箭头函数使用外部做用域做为它们本身的做用域,所以箭头函数也将this
设置为咱们的Vue组件。
这容许咱们经过this
访问 Vue 组件并更新dataFromServer
。
可是,若是须要将函数传递帮助库,好比lodash
或underscore
,该怎么办呢
假设咱们的Vue组件上有一个要使用Lodash
或Underscore
方法。如何防止this is undefine
的错误。
若是你用过 React ,你可能见过相似的东西。
这是咱们用Vue作的。
created() { this.methodToDebounce = _.debounce(this.methodToDebounce, 500); }, methods: { methodToDebounce() { // Do some things here } }
就是这样!
咱们要作的就是获取函数,将其包装在debounce
函数中,而后返回一个内建了debounce
的新函数。如今,当咱们在Vue组件上调用this.methodToDebounce()
时,咱们将调用debounced
版本。
如前所述,常规函数和箭头函数之间存在差别的主要缘由与词法做用域有关。来分析一下它的含义。
首先,做用域是程序中存在变量的任何区域。在Javascript中,window 变量具备全局做用域,它在任何地方均可用。尽管大多数变量被限制在定义它们的函数、它们所属的类或模块中。
其次,单词“词法”仅仅意味着做用域由你如何编写代码决定。某些编程语言只在程序运行时才肯定做用域内的内容。这可能会让人很困惑,因此大多数语言都只使用词法做用域。
箭头函数使用词法做用域,而常规函数和简写函数不使用。
这里最棘手的部分是词法做用域如何在函数中影响 this
。对于箭头函数,this
与外部做用域的this
绑定在一块儿。常规函数的this
绑定方式有些奇怪,这就是引入箭头函数的缘由,也是为何大多数人尽量多地使用箭头函数的缘由。
下面是一些示例,它们演示了做用域如何在这两种函数类型之间以不一样的方式工做
// 此变量在 window 做用域内 window.value = 'Bound to the window'; const object = { // 此变量在 object 做用域内 value: 'Bound to the object', arrowFunction: () => { console.log(this.value); // 'Bound to the window' }, regularFunction() { console.log(this.value); // 'Bound to the object' } };
咱们可使用 bind 方法来改变 this
的绑定
const boundFunction = unboundFunction.bind(this);
这使咱们在编写Vue组件时具备更大的灵活性,更轻松地重用方法。固然,可读性相对差点,应该尽可能避免太频繁地使用它。
代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug。
原文:
https://www.techalyst.com/pos...
文章每周持续更新,能够微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,另外关注公众号,后台回复福利,便可看到福利,你懂的。