美文网首页
跑题式,逻辑混乱式思考笔记

跑题式,逻辑混乱式思考笔记

作者: wudimingwo | 来源:发表于2018-11-23 22:47 被阅读0次

    复用性,维护性,可读性
    效率编程
    作为一个小白的思索.

    刚开始学的时候,是不怕重复的,
    反倒是希望重复的.
    因为我要加深印象,进行记忆, 所以如果有写的机会,
    我是愿意写的.

    后来基本会写了之后,
    就会发现总会出现好多重复性的东西.

    比如 我每次写一个html 都要有 一系列的基本结构标签,
    比如 每次写 js 总会用到很多 for 循环, if else , 或者每次获取dom元素,
    都要写 document.getElementByClassName,
    有段时间, 感觉很浪费时间, 效率很低,
    我就想, 能不能用 代码提示来解决.

    到今天用的是hbuilder , 也许我要改成 vs-code,
    因为其他人都在用这个,,不过,可能是刚开始就用了hbuilder的原因,
    我用的很舒服, 就是整个软件的 ui丑了一点点,

    当时,用hbuilder 对 常用的 一些结构, 比如for,if,还有好多一些, 都进行了代码提示的封装.
    当然 hbuilder 本身对代码提示做的也很好.

    不得不说,这确实节省了我很大的时间.
    这里有个小注意是,
    刚开始封装的提示, 使用起来会很慢, 因为没记住,而且相比习惯的码字,似乎更慢.
    而且知识点记忆起来都嫌累,何况还要记忆一些无关的.
    但还是试着用了起来, 结果无一例外 熟悉了之后,绝对比原来的快.
    也就是说, 假设熟练度最后会达到一样的水准时, 用提示绝对比 码字要快.

    后来就常听说,要模块化封装.
    为了复用性,维护性,可读性.

    首先,我觉得,复用性的实现是 最基本原理是,
    变量的取值?

    只要我 var a = 10 声明一个变量,
    那么 我可以在下面多次引用这个 a
    如果该变量是个函数 那就 a();
    这就完成了最基本的复用啊.

    也就是说,我们想要完成复用,
    首先就要封装成一个变量.
    一个可以访问的变量.

    所有的变量都可以访问嘛?

    什么是不能调用该变量的地方?

    1. 函数的限制
    function fn () {
                var a = 0
              }
              console.log(a);// 报错
              fn();
              console.log(a);//报错
              
    

    函数内部的变量, window中是无法访问的.
    (里层函数的变量,外层函数是无法访问的.)
    但函数内部是可以访问 window的.

    依次可以实现,变量私有,防止全局污染.

    如何才能访问函数内部的变量?

    需要在函数内部返回一个 window 能够访问的接口.

    可以用return 返回,用window的变量接收的方式

              var a = (function () {
                var b = 3;
                return b
              })();
              console.log(a);// 3
    

    可以是 在 函数内部,把变量定义在 window上.

              var a;
              (function () {
                var b = 3;
                a = b;
              })();
              console.log(a);
    

    可以在定义变量的时候, 直接定义在该函数身上.
    (说实话,我碰到的这种用法挺少的.)

          function name() {
            name.a = "a";
          }
          console.log(name.a);// undefined , 因为函数还没执行, name.a 还未被创建赋值.
          name();
          console.log(name.a);// "a"
    

    或者也可以定义在原型链上,
    原型链并非new才会创建.函数定义的时候,就已经创建了.
    通常是为了继承,原型链上定义的一般是函数

          function name() {
          }
          name.prototype.a = "a"
    

    还有就是,返回的实例上, 需要用window的变量来接收该实例

          function Name () {
            this.a = "a"
          }
          var instance = new Name();
          console.log(instance.a);
          当然也可以不用变量接收.
          console.log(new Name().a);
          但要记住,不用变量接收时,就无法完成复用啊!
          
    
    1. 对象的限制.
    var item = {};
    item.a = "a";
    

    item 可以说是定义在了 window上,
    但严格来讲 a 不能说是定义在了window 上, 而是定义在了item上?
    当然我们可以通过 item 获取 item.a

    我想说的是,虽然归根到底,应该算是定义在了window上,
    但如果找不到正确的路径,也是无法访问的.

    1. 存在于其他文件的限制.
      另一个文件的变量,
      如果不引用文件,就无法访问该变量.
      我说了句废话,,

    如果我想访问另一个文件的变量怎么办?

    第一种,复制粘贴啊,我直接把代码复制过来.
    别笑, 作为一个小白, 我经常这样.
    甚至我有想过,干脆把整个插件的js, 用代码提示存起来,
    需要的时候, 直接两个提示代码就能生成整个文档.
    我觉得这没什么好笑的.
    虽然还没这么试过, 但应该也是有一定的便利性.

    第二种方式是,文件引入,
    文件一旦引入就会拥有同一个window了.
    就可以访问该变量了.


    当我说想要实现复用的时候,
    实际上,我是出于想减少一些重复性的劳动,

    而我发现写同一个项目的时候,
    常常会书写同样的字符,
    同样的语句,
    同样的结构,
    同样的功能(或者类似的功能)
    写不同的项目的时候,
    也会常常书写同样的字符,语句,结构,功能.

    所以我要抽象出那些看似类似的部分,
    分析那些类似的部分的概念到底是什么,
    然后封装成一个变量.
    重复引用,就完成了复用.

    但当我们说为了效率编程,实现复用的时候,
    一般是指可执行的代码的复用,
    而不是 数据的复用.

    我们可以把一些代码封装成函数.
    或者我们可以把所有的代码 都看成是函数.

     var a = 0
    可以看成是
    var a;
    function test () {
      a = 0
    }
    test();
    呵呵,是有点牵强.
    

    但这样一个函数,可复用性高嘛?
    我们有一种下意识的判断,感觉复用性不高啊.
    感觉不会经常用啊?为什么呢?这个感觉从何而来?
    我想了一下,
    首先是这个概念.
    这个函数的概念是, 我让 a = 0;
    只适用于 变量 a 啊

    我们可以改成

    var a;
    function test (a) {
      a = 0
    }
    test(a);
    

    咦? 感觉复用性强了一点?
    这个概念变成了, 我传的任何变量,都要变成0
    适用的数据变广,复用性就增强了?

    那依照这个思路,
    我们可以改成这样?

         var a;
    
          function test(a) {
            if(Array.isArray(a)) {
              var len = a.length;
              for(var i = 0; i < len; i++){
                a[i] = 0;
              }
            }else{
              a = 0
            }
          }
          test(a);
    

    这个概念就变成了,任何数,或者任何数组的元素,都会变成0
    复用性增强了嘛?

    不知道,反正我觉得,想要判断复用性强不强,
    首先应该看他的概念,和他的需求.
    如果这个需求很广泛,概念复用性就会越强?
    像 + - * / 这些概念的复用性就非常强.

    思而不学则殆,
    思考一会儿
    不行的时候,就要看别人的.
    如何设计循环避免代码重复,提高代码复用性
    感觉这位在写这一篇的时候,是跟我一样的小白.

    没错啊,
    刚开始我接触数组和循环的时候,也觉得能省好多重复性代码.

    也许应该再换一个角度思考.
    我们刚才在上面说到,概念才是能够判断复用性的关键.
    实际上,根据经验是这样的.
    我们再写某些项目,某些代码的时候,
    我们有时,能够感觉到,咦? 某些需求的类似.
    这些需求的解决的背后,存在某种相同的东西.
    我们只需要把这些东西抽象出来弄成概念,
    再把这个概念,
    弄成插件,就可以完成一个复用性相对高的代码了?

    这需要什么?
    需要学会去观察自己写代码的思路和概念,
    我们写代码的时候,必然都可以翻译成某些概念的吧?
    或者说,我们写一个项目的时候,
    总是会存在一个思路的吧?
    而不同的项目,总会有一些思路是类似的吧?
    我们观察这些需求,观察这些思路.应该是很有必要的.

    或者我们也可以观察自己写的代码,
    如果我能发现我写的不同代码之间的重复的地方,类似的地方,
    我就能抽象出来,
    比如,我总用 if else? 或者getElementByTagName?

    又或者我们可以问题为导向.
    每次写代码的时候,不会总是一帆风顺,
    总会遇到各种各样的问题,
    也许这些问题一直分析,一直抽象,能够抽象出一些类似的地方?
    其实常常有时候,我会遇到某些问题,某些需求,
    但我无法提出正确的问题.

    其实我感觉,这几方面我都很懒.

    先到这里?

    不同的项目,需要的js 代码不同,
    有时需要代码块 a , 不需要 b
    那就可以把 a 和 b 分成不同的文件.
    作为一个小白, 刚开始,我很反感这种文件的引入,
    感觉动作很大,而且很不熟悉.
    现在觉得这还真是天然的模块化.

    第一种函数里的变量,
    可以对我的代码产生影响,但我有可能完全无法访问.
    第二种对象里的变量,
    可以对我的代码产生影响, 但我总有路径可以访问.
    第三种, 只要引入了,就受到第一,第二种的影响.

    我要转变思路的是, 第三种才有可能是常态,正常状态,
    也就是多个文件的组合,或者将代码分割成多个文件.
    这样我才能按需要随意组合.

    极端情形是,
    我希望每个功能, 比如 function add (x,y) {return x + y};
    就这一个函数,我希望他都能拆分成一个独立的文件.
    为什么?
    因为,按照拆分的思想,
    终极状态时, 最后我运行的代码中,
    不存在我不需要的代码,不需要不会运行的代码.一句都没有.
    不过很明显,这样做的话, 可能我的代码里,可能会出现很多很多的引入.
    满篇都可能是 import
    不过,终极想象是, 我们拥有类似webpack 构建工具,
    每个包,都会附带依赖图,
    不需要我们自己去一个一个去添加?
    并且最后会打包成一个完整的文档.
    而不是互相依赖的多个文档.

    上面的思路是,不停的拆分,
    也就是颗粒度变小,降低复杂度,提高耦合度.

    我个人觉得最理想的状态是,所有的插件,所有的组件,所有的依赖,
    我都非常的清楚,我明白每个细节的原理,我知道每个内部的结构设计思路.
    甚至每个代码我都能手写出来.

    但这是不可能的.(可能嘛?)

    因为人类的信息处理能力是有局限的.
    而且如果我必须知道,所有插件的内部原理才能用这个插件的话,
    那很明显,这个学习成本太高了.

    所以我们编程追求的另一个方向是,黑箱子,面向接口,高内聚.
    也就是, 我们只需要有哪些接口,每个接口可以放哪些参数,怎么样放参数,
    还知道最后的效果是什么.就可以了.
    我们只需要知道通过某个接口,参数和效果之间的简单粗暴的因果关系就可以了.
    很明显,这样子会大大提高学习效率,使用效率.

    也就是说, 最好是,封装成, 内部原理什么都不需要知道, 但操作起来特别方便.
    效果还特别好.就可以了.

    说着说着,感觉就是电脑和手机嘛.我给用户提供一个iphone,用不着用户会 编程,
    不会编程,并不影响用户用手机.手机内部的原理可以一概不知,但用户知道操作和效果之间的因果关系.

    按照这种标准,最好的插件就是,傻瓜式操作,根本不用学习什么东西.
    反正就是特别好用.

    其实到现在为止我也有这个疑惑.
    我总怀疑我算不算是个编程人员.
    因为总感觉,我压根不理解所谓的"底层原理",
    什么是底层原理呢?我发现纵向上永远都存在底层原理.
    比如说,当我是用户的时候, 我只会打开浏览器看视频,
    现在我大概明白浏览器是个怎么回事, 知道有 html,css,js,
    知道有dom, 有渲染,有网络请求,
    可你发现每个的背后都有所谓的底层,
    比如浏览器的js引擎内部是怎么回事?
    渲染引擎是怎么回事?
    可是我怀疑即使我知道这俩怎么回事,
    还是会存在"底层原理",
    操作系统的原理,或者还有更底层的.

    如果从这个角度来讲,
    那些用word的也算不算是一种 编程人员?(应该不算?)

    问题很自然的就来了.
    我们需不需要知道"底层原理"?
    答案是需要的.但又需要分情况.
    首先,按照我在学校学习的整个经验来看,
    从来都是先学理论基础,然后再学这个理论的应用.
    总是从基础开始,从理论开始.
    这样子学习是对的,从某种角度来讲也是最有效率的.

    我们为什么需要知道"底层原理"?
    首先,以一个插件为例, 我们深刻理解的他的内部结构和设计原理,
    肯定对于我们正确,有效的应用该插件是有帮助的.
    特别是,有时候,我们会遇到这个插件的期望效果和实际效果不一样的时候.
    或者,总会遇到使用范围的问题,
    尽管文档的操作说明里可能写的"很完善",
    但我们有时候还是要不停的去"试一试",
    某些情况的时候, 会有怎么样的特殊表现,诸如此类.
    你比如说,margin塌陷,
    vertical-alighn的表现.
    光看文档的时候,很难完全理解,或者很难完全掌握操作和效果之间的所有因果关系.
    甚至我学习jq的时候也有类似的感觉.
    此时我就感觉非常的"累",这种累是因为,我记忆这些因果关系的时候,
    是没有理论支撑的,或者说,我是硬背的,
    我没有一个更好的理论来解释这个因果关系.

    这个时候,知道一点"底层原理",就有助于我们解释,理解.

    到目前为止,
    我的前端的学习过程,很明显不是完全依照,先基础理论,再 应用这样的模式.
    常常是,先应用,先学会怎么用, 知道是用来干什么的,
    掌握差不多之后,再返回去理解他的底层结构和设计原理是什么.
    这样的学习方式,实际上效率也挺高的.
    而且从某种角度来讲也更合理.
    因为可以在不懂原理的时候就可以用了.

    知道越多的底层原理,我们就越能应用的更好, 我们的应用范围就会越高.
    但学习底层原理是需要学习成本的.
    我们要解决一个问题,可能面临两个选择,
    一个是我理解了底层原理之后, 在去解决这个问题.
    另一个是我找到别人设计的超牛逼的插件,组件,框架 只需要按照文档傻瓜式操作,
    我就能立马解决这个问题.
    你说我选择哪一个?
    我觉得必然要先选牛逼的插件啊!
    因为,我面临的实际选项其实是, 我是要先解决问题? 还是要先学习?哪个更重要.
    我觉得既然用高效率的方式解决问题,能更省时间,必然应该是先解决问题,
    然后慢慢去研究怎么实现的.

    就好像,有一把枪摆在我面前, 前面有个问题是老虎,
    我是先一枪崩了它再说,还是先设计一个矛,在设计一个刀,在设计一个弓箭,
    在研究一下火药,在更深入研究一下制铁技术,最后再弄出一个枪来干掉那个老虎?
    也许老虎都睡着了.

    当然了,我相信这也是绝大多数编程人员的选择.
    做出这个选择很必然,但问题是,我用脚指头想的(瞎猜的)是,
    可能存在很多编程人员的思路就变了.
    他的思路就变成, 我要针对这把枪去练习枪法.要百步穿杨.
    或者变成,有没有更好的枪?更好用的枪?
    也就是,他不太可能再好好研究武器的历史,枪的内部构造原理什么的.
    (我可能也是这样的)
    但我的合理想象是, 知道枪的内部原理,就相当于学习内功,
    知道了内功总是比较容易成为高手, 而且更容易适应新出的招数.
    (如果想走的更远,就必须学习底层原理,到到底什么所谓的底层原理就要另外思考了)

    回到正题.
    正题是什么?
    我们之所以提到底层原理的原因是,
    所有好的插件啊,文档啊,他们的也会教你,
    但他们确实好啊,就是想让你用更少的学习成本,学习更傻瓜式的操作方式.
    更傻瓜式的因果关系.

    正题是,必然的一个现象是, 我会用,但我不知道其内部原理.
    肯定有啊,你敢说你用的所有的api 的背后结构原理都了解的一清二楚?

    我想说的是,
    黑盒子,面向接口的编程是必须的.
    换言之,我上面讲的个人觉得的理想状态, 我知道所有插件的底层原理,然后再用,是不现实的.
    (话题回来的好不自然,好牵强.)

    我想了想,想要面向接口,实现黑盒子,
    我们就要定义好功能,定义好需求,定义好概念,
    所谓的高内聚,我猜是不是就是这样的,
    先进行细的拆分,减小颗粒度,
    然后根据功能,需求,概念进行内聚.封装成整体,实现黑盒子.

    上面的过程,先是降低颗粒度,然后内聚生成的黑盒子的颗粒度又变高了.
    这里就必须插入另一个话题了.
    暂且称为颗粒度的高低的问题.
    颗粒度越低,其复用性就越强.适用范围越广.
    颗粒度越高,其目的性就越强.适用范围可能会缩小.

    比如, for() if else ,这个算不算api? 我们假设算.
    这个的复用性,适用范围就太广了,
    对应的基本概念是, 遍历, 以及 如果.

    再看数组的几个方法 forEach every some reduce
    严格来讲, 这个是 通过 arr 和 for 循环组合而来的.
    对应的概念是, 对数组进行遍历操作.
    对数组进行遍历操作后要么筛选,要么判断,要么返回某个值.

    这个颗粒度变高了点, 但适用范围依然非常的高.

    我们现在想干什么? 想找出什么决定一个插件,功能的适用范围?

    相关文章

      网友评论

          本文标题:跑题式,逻辑混乱式思考笔记

          本文链接:https://www.haomeiwen.com/subject/ecnsqqtx.html