尝试在Vue中的methods定义几个函数,实现函数A调用函数B的需求。但是发现通过this关键字引用会提示 B函数not defined
报错信息如下:
实际上个问题的根本原因是函数以及子函数的this作用域范围处理问题
Vue中this作用域说明
参考文章:
Vue里this指向
如何修复Vue中的 “this is undefined” 问题
对于一个Java程序员来说,真的需要了解下这个this的作用域,因为和Java的差别还是有点大的。因为Java中的this默认都是指向当前的类,但是 Vue的作用域是以函数为单位划分的
从上面的文章归纳总结就是:
- methods中通过xxx:function(){} 或 xxx(){}的方式定常规义函数,默认的this都是指向外部的Vue对象
- 箭头函数,无论是在methods中定义的函数,或者是methods的嵌套子函数,都是不存在this对象的,默认都是继承与父函数的this
- 假若在methods的函数中嵌套子函数function xxx ,function xxx的this作用域是指代xxx函数内部,而不是外部的Vue对象
光说还有点绕,因为这边有几种情况需要做例子说明才好说明。因为涉及到普通methods定义以及箭头函数、子函数的定义处理。
这里划分四种情况:
- Vue->methods中使用常规函数
- Vue->methods中使用箭头函数
- Vue->methods中的常规函数,定义内部子常规函数(目前题主遇到的问题)
- Vue->methods中的常规函数,定义内部子箭头函数(这个)
按照上面的设想,我们写了一套测试代码,以及输出对应的验证效果,主要看代码注释就好了
Demo代码
// DES: Vue下的methods函数 methods:{ outerFunction() { console.log("this is outer function") }, innerFunction() { console.log("this is inner function"); // DES: 调用Methods下的其他函数,因为Vue中默认methods的函数都会持有Vue实体对象,所以直接调用不会出现问题 this.outerFunction(); // DES: 调用Methods下的箭头函数 this.arrowFunction(); // DES: 创建_this成员变量,保存Vue对象的引用,常用于子函数调用vue对象的情况 let _this = this; // DES: 内部子常规函数 function testInnerNestedFunction() { // DES: 因为刚刚说过,js的作用域是根据function定义的,所以这个this指向的是testInnerNestedFunction的this console.log("子常规函数输出this:" + this); console.log("子常规函数输出本地变量_this:" + _this); // DES: 按照刚刚的说法,这个outerFunction就是undefined的了,因为this指向的是testInnerNestedFunction函数自身 this.outerFunction(); } // DES: 内部子箭头函数,Es6定义的箭头函数是不存在this的,默认是继承父函数的this,即继承了innerFunction的this,即Vue对象 let testInnerNestedArrowFunction = () => { console.log("子箭头函数输出this:" + this); console.log("子箭头函数输出本地变量_this:" + _this); // DES: 因为继承this,所以直接调用outerFunction是没问题的 this.outerFunction(); }; // DES: 因为先调用testInnerNestedFunction的话会抛出异常,这里执行顺序先改变下 testInnerNestedArrowFunction(); testInnerNestedFunction(); }, arrowFunction: () => { // DES: 按照刚刚设想,这个this没有继承到Vue这个对象,所以this是undefined的 console.log("Methods 箭头函数输出this:" + this); // DES: 因为这里会报错就先注释掉了 //this.outerFunction(); } }
输出结果如下:注意子函数的输出,再对比下代码会理解更加深刻
所以this作用域的建议有这些
- 假若Methods中函数的子函数需要调用Methods同级函数有几个办法
- Methods同级函数提取到export default节点下
- 子函数定义使用箭头函数
- Methods函数内通过let _this = this; 保存外部vue对象,然后子函数就使用_this的对象而不是this
- Methods层级的函数不建议用箭头函数
- Methods层级的函数的子函数尽量都用箭头函数,因为会默认继承Methods层级的this(Vue)对象
所以刚刚我的问题也很容易解决吧。把promise构造函数的函数调用改为箭头函数即可