V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
kamushin
V2EX  ›  JavaScript

有的时候真的不知道 js 这些东西是怎么被设计成这样的....

  •  
  •   kamushin · 2015-07-26 00:11:36 +08:00 · 4206 次点击
    这是一个创建于 3190 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如obj的key只能是str....我想做个以对象为key的map还要自己调用hash
    比如for(i in array)返回的是key的列表,喂,你是把自己当map了吗....for(i of array)才等同于Python里的for i in array...说实话以我的弱渣英语真不懂这里in和of都有啥能让人记住的区别
    比如split()居然返回的是自己...靠..你默认\n或者空格都行啊..返回自己是个什么设计...

    第 1 条附言  ·  2015-07-26 03:02:15 +08:00
    我本来发这个帖子,除了想吐槽外(不是黑),主要想看看我的第一个需求,写js的人会用什么优雅的方式解...可惜一半的人上来先说,这是js的特色啊/黑得不在点子上...嗯
    39 条回复    2015-07-27 14:21:41 +08:00
    riaqn
        1
    riaqn  
       2015-07-26 00:15:05 +08:00   ❤️ 5
    如果js/perl/bash的设计者在同一架飞机上,那我一定会不惜一切代价把他炸了.
    bramblex
        2
    bramblex  
       2015-07-26 00:16:15 +08:00
    这……貌似喷都没喷到点上唉……
    bramblex
        3
    bramblex  
       2015-07-26 00:19:05 +08:00
    @riaqn

    然而prel风格的正则大法好,正则是处理字符串的利器。
    然而bash光一个pipe+重定向就秒天秒地了。
    然而js……嗯,js大法好! /w\
    NemoAlex
        4
    NemoAlex  
       2015-07-26 00:23:47 +08:00
    前端的东西比这乱的多了去了,说明还是见得少。
    这都受不了的话,去试试世界上最好的语言,提升一下免疫力。
    sox
        5
    sox  
       2015-07-26 00:26:25 +08:00 via Android
    我就静静地看着你装逼。
    kamushin
        6
    kamushin  
    OP
       2015-07-26 00:28:12 +08:00
    @NemoAlex 最近在看看为什么node这么火爆。所以也不算在接触前端吧。前段时间工作需要看别人写的Perl代码,除了觉得奇怪的字符比较多以及奇怪的scalar以外,感觉也还好。。。
    @bramblex 没有啦。我并没有在喷。只是学习中吐槽一下。而且我也是新手,肯定喷不到点上。
    edsgerlin
        7
    edsgerlin  
       2015-07-26 00:30:07 +08:00
    @riaqn Perl 其实很有 consistency,只要你学会用 Larry Wall 的脑回路思考,设计风格是很一致的。相比之下 PHP 就是设计者拍拍屁股就加个特性的表率。
    YuJianrong
        8
    YuJianrong  
       2015-07-26 00:32:07 +08:00 via iPad
    吐槽的点都好怪,而且你都用es6的for of 了为何不用es6的map?有in了还来个of很自然就能知道是不能破坏以前in的语意呗……

    学语言都要了解一下特定语言的一些怪癖,Js有这些其他语言何尝没有……
    YuJianrong
        9
    YuJianrong  
       2015-07-26 00:34:39 +08:00 via iPad
    顺便es从5开始设计就很不错了,大多数坑都是在最初版埋下的为了兼容没办法改(比如 typeof null是object),不过由于第一版js很简单其实这些坑也不多的。
    kamushin
        10
    kamushin  
    OP
       2015-07-26 00:41:39 +08:00
    @YuJianrong 恩,其实我就是在学这些怪癖,但是这些怪癖我真是怪的想吼出来了....
    yakczh
        11
    yakczh  
       2015-07-26 00:45:28 +08:00
    console.log(Function instanceof Object); // true
    console.log(Object instanceof Function); //true
    console.log(Object instanceof Object); //true
    console.log(Function instanceof Function); //true
    lwbjing
        12
    lwbjing  
       2015-07-26 00:47:51 +08:00
    太年轻。。我们切图仔写两行JS容易么。。。
    yakczh
        13
    yakczh  
       2015-07-26 00:48:53 +08:00
    console.log(Function === Function.constructor ); //true
    console.log(Object === Object.constructor ); //false
    终于出现了一个false
    yakczh
        14
    yakczh  
       2015-07-26 00:52:08 +08:00
    console.log(Object.constructor); // [Function: Function]
    console.log(Object.constructor.__proto__); //[Function: Empty]
    yakczh
        15
    yakczh  
       2015-07-26 00:57:12 +08:00
    console.log({} === {}); //false
    kamushin
        16
    kamushin  
    OP
       2015-07-26 01:04:48 +08:00
    @lwbjing 我真的觉得你们挺不容易的....在es6前,你们是怎么忍受少了这么多功能的...上面那个哥们说的各种true false也懒的去说了...
    kamushin
        17
    kamushin  
    OP
       2015-07-26 01:07:31 +08:00
    @YuJianrong 我比较能接受保留in原来的for(key in array),加入for(key,value in array)...
    tushiner
        18
    tushiner  
       2015-07-26 01:26:12 +08:00
    用到了就习惯了,想当初第一节编程课上老师都说过,语言都是相通的,只是语法不一样,一种语言能实现的东西,其他语言肯定能实现。还有,我刚刚在segmentfault回答你的问题了。。。换了个地方又见到了你。
    Wangxf
        19
    Wangxf  
       2015-07-26 01:29:53 +08:00
    一直不明白别人喷js的原因是什么,你们觉得和你们之前学的不一样的地方正是js的特点,我喜欢
    monnand
        20
    monnand  
       2015-07-26 01:39:59 +08:00 via Android
    tushiner
        21
    tushiner  
       2015-07-26 01:45:09 +08:00
    @monnand 把js黑到极点了,笑cry
    monnand
        22
    monnand  
       2015-07-26 02:20:29 +08:00
    @tushiner 黑js的简直都快成一个产业了。比如还有这个: https://www.destroyallsoftware.com/talks/wat
    w88975
        23
    w88975  
       2015-07-26 02:34:05 +08:00
    我还以为是什么呢 黑都没黑到点子上 当初js设计是用来于DOM交互的,说白了 就是用来操作HTML页面的,根本没考虑过现在居然还能用来写后端.
    kamushin
        24
    kamushin  
    OP
       2015-07-26 02:51:33 +08:00
    @Wangxf 原因是不爽,至于为什么不爽,就好像你学物理的时候感觉数学上的一些知识直接拿来用是可以的,但是学语文的时候数学的知识突然全没用了...
    kamushin
        25
    kamushin  
    OP
       2015-07-26 02:53:19 +08:00
    @w88975 原来黑还要黑到点子上。不爽还要不爽到别人也不爽的地方?或者你觉得我说的这些其实挺爽的? 这位同学活着有点累吧。
    FrankFang128
        26
    FrankFang128  
       2015-07-26 02:57:27 +08:00 via Android
    JS 符合摩尔定律,每过一段时间复杂性翻倍。
    YuJianrong
        27
    YuJianrong  
       2015-07-26 09:03:57 +08:00 via iPad
    @kamushin 你问第一个有什么解答我说了es6的map了。
    我想说的是语言都有其特色,你不能学了其他语言再用C的时候抱怨C没有gc没有map甚至连链表都没有吧?要用什么东西就用那个东西的特色,单纯抱怨真的很没意思。
    没有的东西自己创造就行了,都是程序员不是吗?
    kamushin
        28
    kamushin  
    OP
       2015-07-26 10:32:37 +08:00
    @YuJianrong 恩。我说了是一大半人。另外,我之所以不会吐槽C没有map,是因为C真的没有map。而js有一个map<srting,Any>..也就是一个本来应该是泛型的东西弄了个偏特化出来了..这真的让我觉得有点接受不能,都已经帮忙实现了map了,为什么还要加上这个限制呢(我觉得是限制,而不是功能子集,也就是说实现一个泛型的和实现已经有的这个,代码没啥大区别,但是偏偏就是限制了只能用string)
    realpg
        29
    realpg  
       2015-07-26 10:48:10 +08:00
    我觉得你只是在吐槽js不符合你的python习惯
    说实话,一个牛逼的JSer可能也对你提出这俩问题反过来吐槽python是谁设计的
    YuJianrong
        30
    YuJianrong  
       2015-07-26 11:05:46 +08:00 via iPhone
    @kamushin 当你说范型偏特化的时候,已经是在以c++的角度来看待JS了。那是不是我用了es6的map之后,就可以抱怨C++ map的key必须固定类型不能像es6那样动态。你看都实现静态类型的map了,为什么不实现一个运行时动态类型作key和value的map呢?

    回到JS,Js里面那个一直没说自己是map,只是object而已,key只是作为property name,对应到C++就是成员名,C++成员名为什么只能是一个symbol呢(连字符串都不是)?你看把它设计成一个map也未尝不可不是吗?

    然而这有意思吗……你在学习的是JS而不是C++……
    stranbird
        31
    stranbird  
       2015-07-26 11:14:27 +08:00   ❤️ 1
    1. key是uuid本来就是哈希表算法的基础,hash函数就应该是自己设计的。Java里边你要让一个对象是hashable的,也得写hash函数。

    2. 和collection相关的处理统一用lodash或者underscore来处理。_.map(collection, function(value, key) {...} ) 一点问题没有。本来forIn就不在《the good parts》里边。

    3. split提供默认值的话,你难道不会骂娘说为什么要默认成这样,我让你默认是逗号了么?在多数场景下反而会提高debug的难度。不指定separator就默认为undefined,字符串里没有undefined就分不开,返回自己有什么问题么。

    4. 针对第一个需求,如果真的想优雅实现的话。可以自己将普通的hash封装一个hash类,要加入新的键值对时首先调用键的hash函数求出字符串型的uuid,再存入普通hash中,注意处理碰撞,因为js没有链表,应该只能用闭散列。取的时候也调用键的hash函数算一下,再找。

    任何一项特性的引入都会伴随着复杂度的提升。我用python的时候就会觉得,卧槽干嘛简简单单一个字符串要搞这么多编码,卧槽干嘛数据库里边查出来一个数字序列化成json会报错(decimal is not serializable)。这些东西你想想都有道理,因为本来字符串就是bytes+encoding,默认采用utf8或者ascii都犯了过于主观的错误。decimal作为高精度数字类型确实和普通的float/int是不一样的。但是这些人为引入的复杂度对解决问题起到任何帮助了么?想想有多少时间是浪费在处理这种事情上,而不是真正的业务逻辑上了。

    比方说泛型,你觉得map<string, Any>是一个特例,那其实根据scala的思想,没有对类型推演的逆变和协变,泛型也是不够完整的,即便是map<any, any>也是不够泛化的。(http://www.tuicool.com/articles/vaAnmq)

    关于比较,我就问一声,各位大神什么时候会在自己的程序里边写出这样的代码?有多少时候是因为语言设计的缺陷导致自己调了几天bug的?

    我个人的观点是:Javascript有很多傻逼的地方,但是只用到(http://book.douban.com/subject/2994925/)的话,它就已经是一门伟大的语言了。
    sodatea
        32
    sodatea  
       2015-07-26 11:20:02 +08:00 via iPhone
    Object 本意并不是用作 hash,它的坑太多了,所以才会在 ES6 中引入 Map。
    for in 也是,当初设计太不周到,所以引入 for of (for of 涉及到了 iterator,完全是另起炉灶的感觉,在概念上其实不能与 for in 类比了……)。现在一般用 for k of Object.keys(obj) 而不是 for in 了。

    另外同意楼主说的,ES6 之前的 JS 真不好用……
    kamushin
        33
    kamushin  
    OP
       2015-07-26 16:26:10 +08:00
    @YuJianrong 因为运行时动态类型的map在C++中实现要比实现一个静态类型的难。而Js里,原本的实现我觉得已经可以做到传个对象进去当key了。一个是还要很多的工作,一个是限制和不限制。所以我吐槽的是设计而不是实现。对,他本质是个obj。这是实现。但是设计上,他是个k,v map。

    @stranbird > 在多数场景下反而会提高debug的难度。不指定separator就默认为undefined,字符串里没有undefined就分不开,返回自己有什么问题么。
    我觉得挺有问题的,字符串里没有undefined应该告诉我不能对字符串找一个叫underfined的字符。
    @stranbird 拉链法和链表没有什么卵关系。Scala那段没懂你想表达什么,map<string, V> 本来就是 map<K,V>的一个特例,和你后面说的没什么关系。
    stranbird
        34
    stranbird  
       2015-07-26 17:29:56 +08:00
    其实是因为你没有告诉他,它没有义务给你一个它觉得是对的分隔符。

    Scala那段是描述对于泛型还可以有泛型,我想表达的是,如果真的要引入泛型可以没有边界,这是一个设计选择,大多数场景下足够好用,你想要的那个需求要实现起来也很容易。

    拉链法就是用链表来解决哈希值冲突的情况,在所有有指针的语言里用链表实现,在没有指针的语言里用数组模拟链表实现....

    唉,不知道说什么了,对于一些人来说太阳大概是会从东边落下的吧。
    YuJianrong
        35
    YuJianrong  
       2015-07-26 23:44:00 +08:00
    @kamushin 你这个能传对象做 key 也太想当然了吧……首先你觉得用对象做 key 容易?原本人家的对象只需要是个字符串做 key 的 hashmap,所以只要实现字符串有序比较就可以了,现在可好,什么类型都可以了,那你说boolean 的 true和字符串"true" 和 new String("true")要不要是同一个 key?不是的话谁大谁小?然后a[1]和 a["1"] 是不是就要分开了?要考虑的事情一大堆你就一句“原本就可以”啊,什么叫做限制……用 string 做 key 其实就是简单而且也够用而已,那个时候对 JS 没多少需求,有了需求才设计了 map 这东西,然后你可以去看看 Es6的 spec,这 map 根本连个 hashmap 都不是,性能完全不能和 object 比好吧……

    说实话我觉得你这种抱着一种语言的观念去学另外语言的习惯非常不好,别的设计有别的设计的理由(虽然有些是失误比如 typeof null),抱着这种先入为主的观念不是一个学习其他语言的好态度。
    kamushin
        36
    kamushin  
    OP
       2015-07-27 09:10:25 +08:00
    @YuJianrong 我可不觉得是字符串的有序比较。我传个长度为10000的字符串key他还真给我去比较了?我宁可相信内部是hash的。你在说到谁大谁小的时候已经默认是RB树实现的map了。可是我觉得这么应该是hashmap
    @stranbird 但是它有义务Fail Fast。 那比map<K,V>更泛型的是? 直接数组实现就行了,何必数组模拟链表。
    kamushin
        37
    kamushin  
    OP
       2015-07-27 09:17:31 +08:00
    @YuJianrong >那你说boolean 的 true和字符串"true" 和 new String("true")要不要是同一个 key?不是的话谁大谁小?然后a[1]和 a["1"] 是不是就要分开了?
    ===号返回true的,hash值相同,返回false的,hash值不同(先不去管冲突)。能做到判断===,也就能做到hash。
    >说实话我觉得你这种抱着一种语言的观念去学另外语言的习惯非常不好,别的设计有别的设计的理由(虽然有些是失误比如 typeof null),抱着这种先入为主的观念不是一个学习其他语言的好态度。
    这段我认同,只是coding的时候不能抱着先入为主的观念。但是在理解设计的时候,你无法不抱着先入为主的观念,不然如何去比较设计的思想呢。
    YuJianrong
        38
    YuJianrong  
       2015-07-27 11:39:36 +08:00
    @kamushin 那同样问题就是怎么设计hash算法了。各种类型都要做hash和互相比较大小没有难度上的区别(都不容易)。
    sodatea
        39
    sodatea  
       2015-07-27 14:21:41 +08:00 via iPad
    @kamushin 今天仔细想了下这个问题,感觉 JS 的这种设计还是有道理的:
    1. 非要说的话,object 其实可以用其他类型作为键值,只是在使用前会调用 toString 而已……可以理解为这里将 toString 作为一个最偷懒的 hash 方法来用了。要是有人愿意的话,重写一下 Object.prototype.toString 就能实现「任意类型作键值」的功能了嘛;
    2. 考虑到 object literal 的写法,要是允许键值为任意类型,似乎会很脏……现在只允许 string 的话好看很多(可以参考 ES6 computed property names 的写法,真的挺难看的……而且不能用 JSON 表示了)。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1021 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 19:19 · PVG 03:19 · LAX 12:19 · JFK 15:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.