技术解析

发现一种反模式写法,问问大家的意见
0
2021-09-03 10:02:39
idczone

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

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 是针对动态绑定需求设计的,如果没有这个需求,就不要强行使用,哪怕表面上看上去很优雅


如果一定依赖 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);
},
};
```

个人认为在非对象里面用 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));

```

js 里的 this 是我见过的最恶心的东西之一。

个人觉得 js 少了很多东西,OO 很不成熟,所以我看到的大部分 js 库都是函数编程的。

const { sin , cos , tan } = math ;
说实在的,非常恶心这种写法,可能是因为 java 写多了吧。
因为这样子在阅读代码的时候根本就不知道 sin cos tan 是本文件定义的还是引入的,甚至是哪个库、哪个包都不清楚,需要去 import 里面看。
而 math.sin math.cos 就明显多了。

Java 里面 import static 可是后来才加的特性,ES 也照抄了。真的,对 JS 程序员来讲多学一点 Java 是有好处的,然后记得换一个支持 Go to definition 的 IDE。

生搬硬套,半桶水,以为写了个对象就叫面向对象了。

就一个解构,C++都有的写法,为啥会恶心。
解构出来的场景大部分是个局部变量,方便优化。

既然要持有相关量,为何不用闭包?

我选择
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}
})()

其实我根本不知道搞这些东西在干什么,尤其是写了 Go 之后。

对了,Math 不是自带 tan 么?
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/tan

差点忘了黑一次 NPM,看看 lodash-modularized,就 NPM 这种风气,import module; module.method 这种写法?不存在的!

https://www.npmjs.com/search?q=keywords:lodash-modularized

楼主的代码就有问题了,没有哪个语言直接定义对象来定义 this 的关系。这根本不是面向对象好不好
js 就因为对象定义就直接用对象? 你这个写法完全不符合闭包的策略 /

用 class 来写就好懂很多。

static 特性用的不多,而且跟 node 这种类似,不直观,基本不用。

局部变量我是认可的,比如在一个局部函数里面,但是现在看看 npm 上的库,多少事直接在库文件根结构直接就用这中写法,美其名曰只引入需要的库,减少依赖,也是醉了。

非对象,非 new 的用例为啥要用 this?
知道有坑就绕,而不是学如何从坑里爬出来。

非 OO 开发时,JS 的 this 毫无使用的必要。

这就是所谓的引战帖吧。明明是 LZ 自己写的一坨翔,本来是静态方法的东西偏要加 this,还说自己写的“看上去很优雅”,啧啧。

正确的做法是这样。
```
function sin(val) {
return Math.sin(val);
}
function cos(val) {
return Math.cos(val);
}
function tan(val) {
return sin(val)/cos(val);
},
const math = {
sin, cos, tan
};
```
什么`this`啊, `Function.prototype.bind`啊其实都是糟粕,能不用就不用

有一个很核心的思路是,尽可能降低函数对外部环境的隐式依赖,同时函数执行时不应该隐式地影响外部环境。
函数之间的关联应该是通过参数的传入联系起来的。
使用了 this 实际上就依赖了调用环境上下文,是一种不好的做法。

对啊,这个明显是函数式写法啊,为什么要加 this

“论如何同时激怒两拨人”
写一个函数式的代码,并且用上 this 并开始谈论对象。
----
const sin = this.sin ;
const cos = this.cos ;
这两行直接删去即可。

js 严格来讲没有“对象”
class 也只是模拟,将来指不定就成了糟粕

js 是没有类吧,js 无处不在的对象,你总不能说那是个哈希表吧

删去能运行刚好是碰运气,后面写成 const { tan } = math 不引入 sin cos 就无效了

你说的对,我话不严谨,是 OOP 里的 oo

你是说静态方法只能在静态方法中被引用吗



意义不明。

楼主对 OO 的理解有严重问题,OO 设计中,成员函数是放在 prototype 或 meta 里面,而不是对象里面。

math 本来就封装好的 为什么再来一次

说 JS this 恶心的应该是那些完全不理解 JS 对象模型的人


JS 的 this 是恶心,这点没得洗,都是历史遗留的包袱。
this 现在大部分情况作为函数的一个额外参数使用,而不是用于调用成员函数,访问成员变量。

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服