发现一种反模式写法,问问大家的意见

2018-12-03 01:00:58 +08:00
 autoxbc

有如下一小段代码,能否发现这里有什么问题?

const math = {
    sin(val){
        return Math.sin(val);    
    },
    cos(val){
        return Math.cos(val);    
    },
    tan(val){
        const sin = this.sin ;
        const cos = this.cos ;
        return sin(val)/cos(val);    
    },
};

一个粗心的程序员可能会这么续写

const { sin , cos , tan } = math ;
console.log( tan(.5) );

这里就会报错了,因为 tan 方法内部需要的 this 对象在解构赋值的时候丢失了。要想正确使用,必须把代码写成这样的丑陋形式

let { sin , cos , tan } = math ;
[ sin , cos , tan ] = [ sin , cos , tan ].map( e => e.bind(math) );
console.log( tan(.5) );

不过,其实只要在开始的时候,把这两行

const sin = this.sin ;
const cos = this.cos ;

写成

const sin = math.sin ;
const cos = math.cos ;

这样,就消除了隐患。显然,对于 tan 方法,动态绑定 this 对象是没有意义的,因为这个值既不会也不允许改变

总结一下就是,this 是针对动态绑定需求设计的,如果没有这个需求,就不要强行使用,哪怕表面上看上去很优雅

6534 次点击
所在节点    JavaScript
35 条回复
yaozeyuan93
2018-12-03 02:32:49 +08:00
如果一定依赖 this 的话, 为什么不在初始化时直接使用呢

```javascript
const math = {
sin(val){
return Math.sin(val);
},
cos(val){
return Math.cos(val);
},
tan(val){
const sin = math.sin ;
const cos = math.cos ;
return sin(val)/cos(val);
},
};
```
sker101
2018-12-03 04:53:50 +08:00
个人认为在非对象里面用 this 没啥意义, 纯粹自找 bug
真要那么用可以

```

const math = {
sin(val){
return Math.sin(val);
},
cos(val){
return Math.cos(val);
},
tan(val){
const sin = this.sin ;
const cos = this.cos ;
return sin(val)/cos(val);
},
};

const { sin, cos, tan } = math;


console.log(tan.call(math, 1));


```
zn
2018-12-03 07:50:40 +08:00
js 里的 this 是我见过的最恶心的东西之一。
0xff0x77
2018-12-03 08:00:19 +08:00
个人觉得 js 少了很多东西,OO 很不成熟,所以我看到的大部分 js 库都是函数编程的。
wangxiaoaer
2018-12-03 08:08:54 +08:00
const { sin , cos , tan } = math ;

说实在的,非常恶心这种写法,可能是因为 java 写多了吧。

因为这样子在阅读代码的时候根本就不知道 sin cos tan 是本文件定义的还是引入的,甚至是哪个库、哪个包都不清楚,需要去 import 里面看。

而 math.sin math.cos 就明显多了。
Jex
2018-12-03 08:22:36 +08:00
@wangxiaoaer Java 里面 import static 可是后来才加的特性,ES 也照抄了。真的,对 JS 程序员来讲多学一点 Java 是有好处的,然后记得换一个支持 Go to definition 的 IDE。
ChefIsAwesome
2018-12-03 08:53:48 +08:00
生搬硬套,半桶水,以为写了个对象就叫面向对象了。
azh7138m
2018-12-03 09:14:52 +08:00
@wangxiaoaer 就一个解构,C++都有的写法,为啥会恶心。
解构出来的场景大部分是个局部变量,方便优化。
zhyl
2018-12-03 09:20:23 +08:00
既然要持有相关量,为何不用闭包?
shintendo
2018-12-03 09:26:57 +08:00
我选择
const math = (function() {
const sin = function(val) {
return Math.sin(val)
}
cosst cos = function(val) {
return Math.cos(val)
}
const tan = function(val) {
return sin(val) / cos(val)
}
return {sin, cos, tan}
})()
petelin
2018-12-03 09:28:54 +08:00
其实我根本不知道搞这些东西在干什么,尤其是写了 Go 之后。
1010543618
2018-12-03 09:36:50 +08:00
Jex
2018-12-03 09:41:27 +08:00
@wangxiaoaer 差点忘了黑一次 NPM,看看 lodash-modularized,就 NPM 这种风气,import module; module.method 这种写法?不存在的!


https://www.npmjs.com/search?q=keywords:lodash-modularized
wly19960911
2018-12-03 09:47:54 +08:00
楼主的代码就有问题了,没有哪个语言直接定义对象来定义 this 的关系。这根本不是面向对象好不好

js 就因为对象定义就直接用对象? 你这个写法完全不符合闭包的策略 /
FakeLeung
2018-12-03 09:54:53 +08:00
用 class 来写就好懂很多。
wangxiaoaer
2018-12-03 10:13:59 +08:00
@Jex #6 static 特性用的不多,而且跟 node 这种类似,不直观,基本不用。
wangxiaoaer
2018-12-03 10:15:45 +08:00
@azh7138m #8 局部变量我是认可的,比如在一个局部函数里面,但是现在看看 npm 上的库,多少事直接在库文件根结构直接就用这中写法,美其名曰只引入需要的库,减少依赖,也是醉了。
Justin13
2018-12-03 10:50:45 +08:00
非对象,非 new 的用例为啥要用 this?
知道有坑就绕,而不是学如何从坑里爬出来。
DOLLOR
2018-12-03 11:16:18 +08:00
非 OO 开发时,JS 的 this 毫无使用的必要。
wxsm
2018-12-03 11:53:57 +08:00
这就是所谓的引战帖吧。明明是 LZ 自己写的一坨翔,本来是静态方法的东西偏要加 this,还说自己写的“看上去很优雅”,啧啧。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/513664

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX