有如下一小段代码,能否发现这里有什么问题?
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 是针对动态绑定需求设计的,如果没有这个需求,就不要强行使用,哪怕表面上看上去很优雅
看到好几个同学说字面量定义本身就是种反模式,并用闭包演示如何解决持有变量
可是,闭包无法实现字面量写法提供的自注册效果,像这样
const math = {
... ,
cot(val){ // <-- 自注册
const tan = math.tan ;
return 1/tan(val);
},
};
const math = ( () => {
... ;
const cot = val => 1/tan(val);
return { ... , tan , cot }; // <-- 手动注册
} )();
1
yaozeyuan93 2018-12-03 02:32:49 +08:00 1
如果一定依赖 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); }, }; ``` |
2
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)); ``` |
3
zn 2018-12-03 07:50:40 +08:00 via iPhone
js 里的 this 是我见过的最恶心的东西之一。
|
4
0xff0x77 2018-12-03 08:00:19 +08:00
个人觉得 js 少了很多东西,OO 很不成熟,所以我看到的大部分 js 库都是函数编程的。
|
5
wangxiaoaer 2018-12-03 08:08:54 +08:00
const { sin , cos , tan } = math ;
说实在的,非常恶心这种写法,可能是因为 java 写多了吧。 因为这样子在阅读代码的时候根本就不知道 sin cos tan 是本文件定义的还是引入的,甚至是哪个库、哪个包都不清楚,需要去 import 里面看。 而 math.sin math.cos 就明显多了。 |
6
Jex 2018-12-03 08:22:36 +08:00 1
@wangxiaoaer Java 里面 import static 可是后来才加的特性,ES 也照抄了。真的,对 JS 程序员来讲多学一点 Java 是有好处的,然后记得换一个支持 Go to definition 的 IDE。
|
7
ChefIsAwesome 2018-12-03 08:53:48 +08:00 1
生搬硬套,半桶水,以为写了个对象就叫面向对象了。
|
8
azh7138m 2018-12-03 09:14:52 +08:00 via Android
@wangxiaoaer 就一个解构,C++都有的写法,为啥会恶心。
解构出来的场景大部分是个局部变量,方便优化。 |
9
zhyl 2018-12-03 09:20:23 +08:00 via Android 1
既然要持有相关量,为何不用闭包?
|
10
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} })() |
11
petelin 2018-12-03 09:28:54 +08:00 via iPhone
其实我根本不知道搞这些东西在干什么,尤其是写了 Go 之后。
|
12
1010543618 2018-12-03 09:36:50 +08:00
|
13
Jex 2018-12-03 09:41:27 +08:00 1
@wangxiaoaer 差点忘了黑一次 NPM,看看 lodash-modularized,就 NPM 这种风气,import module; module.method 这种写法?不存在的!
https://www.npmjs.com/search?q=keywords:lodash-modularized |
14
wly19960911 2018-12-03 09:47:54 +08:00
楼主的代码就有问题了,没有哪个语言直接定义对象来定义 this 的关系。这根本不是面向对象好不好
js 就因为对象定义就直接用对象? 你这个写法完全不符合闭包的策略 / |
15
FakeLeung 2018-12-03 09:54:53 +08:00
用 class 来写就好懂很多。
|
16
wangxiaoaer 2018-12-03 10:13:59 +08:00
@Jex #6 static 特性用的不多,而且跟 node 这种类似,不直观,基本不用。
|
17
wangxiaoaer 2018-12-03 10:15:45 +08:00
@azh7138m #8 局部变量我是认可的,比如在一个局部函数里面,但是现在看看 npm 上的库,多少事直接在库文件根结构直接就用这中写法,美其名曰只引入需要的库,减少依赖,也是醉了。
|
18
Justin13 2018-12-03 10:50:45 +08:00 via Android
非对象,非 new 的用例为啥要用 this?
知道有坑就绕,而不是学如何从坑里爬出来。 |
19
DOLLOR 2018-12-03 11:16:18 +08:00 via Android
非 OO 开发时,JS 的 this 毫无使用的必要。
|
20
wxsm 2018-12-03 11:53:57 +08:00
这就是所谓的引战帖吧。明明是 LZ 自己写的一坨翔,本来是静态方法的东西偏要加 this,还说自己写的“看上去很优雅”,啧啧。
|
21
tommyZZM 2018-12-03 12:09:13 +08:00
正确的做法是这样。
``` 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`啊其实都是糟粕,能不用就不用 |
22
tommyZZM 2018-12-03 12:14:15 +08:00
有一个很核心的思路是,尽可能降低函数对外部环境的隐式依赖,同时函数执行时不应该隐式地影响外部环境。
函数之间的关联应该是通过参数的传入联系起来的。 使用了 this 实际上就依赖了调用环境上下文,是一种不好的做法。 |
23
no1xsyzy 2018-12-03 13:31:17 +08:00
@ChefIsAwesome 对啊,这个明显是函数式写法啊,为什么要加 this
|
24
no1xsyzy 2018-12-03 13:34:45 +08:00
“论如何同时激怒两拨人”
写一个函数式的代码,并且用上 this 并开始谈论对象。 ---- const sin = this.sin ; const cos = this.cos ; 这两行直接删去即可。 |
25
66beta 2018-12-03 13:52:21 +08:00 via Android
js 严格来讲没有“对象”
class 也只是模拟,将来指不定就成了糟粕 |
27
autoxbc OP @no1xsyzy #24 删去能运行刚好是碰运气,后面写成 const { tan } = math 不引入 sin cos 就无效了
|
29
mskf 2018-12-03 19:40:38 +08:00
你是说静态方法只能在静态方法中被引用吗
|
30
rabbbit 2018-12-03 20:17:35 +08:00
|
31
royzxq 2018-12-03 23:08:35 +08:00
意义不明。
|
32
zealot0630 2018-12-04 06:06:21 +08:00
楼主对 OO 的理解有严重问题,OO 设计中,成员函数是放在 prototype 或 meta 里面,而不是对象里面。
|
33
cyssxt 2018-12-04 08:16:59 +08:00 via iPhone
math 本来就封装好的 为什么再来一次
|
34
nullcc 2018-12-04 08:43:42 +08:00 1
说 JS this 恶心的应该是那些完全不理解 JS 对象模型的人
|
35
zealot0630 2018-12-04 19:04:44 +08:00
|