- 纵观JS对象的“简”与“繁”(上)
JS这门语言,曾被不少开发者视为玩乐的语言,没有厚度和技术含量的语言,但发展到现在,想必没有人敢再这么说,它能做的事越来越多,所以,这门语言看似知识结构简单,但却在代码的行与行之间藏着很多细节和玄机。 “对象”在JS中是个很有意思的东西,它随处可见,说简单可以很简单,但也可以复杂到让人头皮发麻。 简单 如何简单? [代码]var person = new Object(); [代码] 这样就可以创建一个名为“person”的对象。 但事实上,没有人会在意它的简单,因为简单的东西往往承担不了重任。 所以,我们可以从另一个角度去理解它的复杂,就是强大——每一种形式,每一个特性,都为了解决更多问题而生。 复杂 像上面那样,我们可以轻松创建一个对象,进一步,为其添加一些属性和方法: [代码]person.name = "idea"; person.age = 18; person.run = function(){ alert("I can run!"); } [代码] 但其实这里我们就会发现需要写很多的“person”,代码不够简洁。 可以进行如下改进,也就是另外一种写法——“对象字面量”: 对象字面量 [代码]var person = { name : "idea"; age : 18; run : function(){ alert("I can run!"); } } [代码] 它有两个优点:简化代码、凸显封装性。 如果你对js不熟,但对css预处理还算熟悉,这就像是less或者sass的嵌套。(后面更深入的东西我还会拿css类比,以帮助理解。 由此,我们可以像这样创建对象: [代码]var person1 = { name : "tom"; age : 18; run : function(){ alert("I can run!"); } } var person2 = { name : "lili"; age : 16; run : function(){ alert("I can run!"); } } ... [代码] 但其实我们好像又发现一点不那么好的地方,这样以来,我们每创建一个新的实例,都要写这么一大块的代码,显然是冗余的,于是,有人发动脑筋,想了一种办法——“工厂模式”。 工厂模式 对于工厂模式,可以这么理解,我们需要制作100个同类的产品,但不需要为每件产品都弄一个模子,而是一个模子可以反复用,生产很多很多产品。 代码就像这样: [代码]function createPerson(name, age, job){ var o = new object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } var person1 = createPerson("tom",18,"teacher"); var person2 = createPerson("lili",16,"doctor"); [代码] 这段代码的亮点在最后,我们可以只用一行代码就创建一个对象,并赋予其属性值。 看起来很不错,但它存在一个难以觉察的不足——我们好像无法获知这个对象的类型。 这么说其实并不准确,每个对象都有其类型,大不了是Object,但这个结果给不了我们更有价值的东西。所以,要引荐出一个对象世界里的重要角色——“构造函数”。 构造函数 先看代码: [代码]function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } }; var person1 = new Person("tom",18,"teacher"); var person2 = new Person("lili",16,"doctor"); [代码] 从面上看,这段代码跟上面那段有这么几点不同: 没有显式创建对象 属性和方法直接给了this 没有返回 创建新实例的时候,使用了“new”关键字 名称首字母大写 为什么说它重要,上面我们只是创建了一个自定义的构造函数,其实js当中有很多内置的构造函数,我们会无数次地使用,比如Array、Date、String等等。 构造函数和普通函数有什么不同?好像只是首字母大写? 这么说也没错,它可以当做普通函数使用,就像这样: Person(“tom”,18,“teacher”); 但当它被这样使用了之后,就是作为构造函数: var person1 = new Person(“tom”,18,“teacher”); 会经历完全不同的过程。 构造函数看起来很好用,但它还有需要改进的地方吗?往下看。 上面那段代码里,有这么一行: this.sayName = function(){ alert(this.name); } 它会为新创建的实例新建一个sayName方法,别忘了,方法是赋予对象的函数,函数本身也是对象,所以,person1和person2是两个不同的对象实例,同样,它们的sayName方法也不同(虽然看起来是一个样子)。 这样以来,name、age和job都共用了,完成同样任务的方法却没有共用,每一个新的实例都会创建一次,显然,这不是最理想的,有办法解决吗? 我们可以做这样的尝试: [代码]function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayName = sayName; }; function sayName(){ alert(this.name); } var person1 = new Person("tom",18,"teacher"); var person2 = new Person("lili",16,"doctor"); [代码] 和之前的区别就在于,我们把sayName方法提到了函数体的外面,意味着,它是个全局的函数,而不属于某一个。 这个时候,你会发现一个有趣的现象,如果你写下这么一行代码: alert(person1.sayName() == person2.sayName()); 它会弹出三个值:“tom、lili、true”。 首先是里面两个分别执行,然后是外层,这说明,它们俩共用了同一个,不需要担心多余创建的那个函数实例。 终于皆大欢喜! 可是…慢着,好像哪里不对? 你可能记得,说对象字面量的时候,我们提到了封装性,你会发现,这里的sayName方法在函数体的外部,如果有很多个,就会有很多个方法散落在外部,这感觉很糟,这不是我们要的,so,必须找到一个办法解决它,就像上面做的那样。 原型模式 我们终于迎来了这个重磅的概念,关于这个概念,往往让人觉得是复杂的,抽象的,高深莫测的,其实并不,让我们来看看它具体的表现: [代码]function Person(){ } Person.prototype.name = "alien"; Person.prototype.age = "23"; Person.prototype.job = "teacher"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); [代码] 我们创建一个函数,但里面什么都没有。 接下来用到了“prototype”,其实每个函数都有一个prototype属性,这个属性是一个指针,所谓指针,就是建立A和B相关联的一个中介,prototype指向一个对象,这个对象,可以为我们提供所有同一类型实例能够共享的属性和方法,听起来是不是很熟悉?——它能为我们带来前面提到的所有。 但这么说似乎仍然不好理解,所以,你应该对CSS很熟悉,prototype,就相当于为所有可能的子元素,提供了一个父元素,这个父元素的所有属性,都能为子元素所共享,同时,它也不限制子元素的行为。 即,person1和person2具备Person.prototype所指对象的所有属性和方法,并且能够对其进行覆盖或者添加自身特有的新属性和方法。 看到这,我们是不是应该准备欢呼“大结局”了呢?的确,已经有不少内容了,可是,事情从来都不像我们想想的那么简单。 来思考一下,原型虽好,但它是否让我们走向了另一个极端?所有的属性和方法我们都需要共享吗?往往并不是,很多时候,对于某个属性,我们只需要私有即可,而不必共有,那么,什么样的属性私有更合适?既具备私有,又能共有的方案,存在吗? 想知道答案,且看下回分解~ 纵观JS对象的“简”与“繁”(下)
2019-03-11 - 从0到1上线一个微信小程序
0.0 前期准备 微信小程序的出现极大地降低了个人开发者微创业的门槛,不需要后端技术,不需要服务器和域名这些乱七八糟的前置操作,只需要懂得前端技术,就能发布一款属于自己的轻量级应用,简直是前端开发者的福音呐😁 现在其实更火的当是微信小游戏,小程序热度排行榜上长期被小游戏霸屏。但小游戏的开发技术栈比小程序要多,需要的人力物力也更大。目前正在研究之中,有时间再做讨论。 在开始之前需要准备一个邮箱去创建一个小程序账号。一个邮箱能且只能创建一个小程序,这让人有点难以理解,每创建一个小程序就要去申请个邮箱账号,小游戏同样是这样,导致我现在都不知道自己有几个邮箱账号了。 0.1 创意 虽然研发成本极大降低,但想要做出一款成功受青睐的小程序,还是需要动很大的脑筋的。据不完全统计,现在市面上已发布的小程序已经几百万个😨,想要在这么多的形形色色的小作品里面脱颖而出,要么就是你的作品非常有创意,戳中了一些人的痛点,要么就是你路走偏锋,做了漏网之鱼😂 相比之下,小游戏却是更能突显创意的战场。2048,围住神经猫,跳一跳这些让人眼前一亮的精致小玩意儿,都是创意制胜的代表。奈何在下也是应试教育的产物,脑子里的创新区域只在做梦的时候才会活跃。假如你想到了一个有趣可行的点子,那离用户百万就已经成功了一半。我一位同事说想做一个实时社交的小程序,让用户可以实现无障碍沟通。我当时就想,这样有理想的人怎么就和我做了同事了呢😂 0.2 技术 小程序的运行环境 小程序的运行环境可以用一句话概括:敌情相当复杂。 在 iOS 上,小程序逻辑层的 javascript 代码运行在 JavaScriptCore 中,视图层是由 WKWebView 来渲染的,环境有 iOS8、iOS9、iOS10 在 Android旧版本 上,小程序逻辑层的 javascript 代码运行中 X5 JSCore 中,视图层是由 X5 基于 Mobile Chrome 57 内核来渲染的 在 Android新版本 上,小程序逻辑层的 javascript 代码运行在 V8 中,视图层是由自研 XWeb 引擎基于 Mobile Chrome 67 内核来渲染的 在微信开发者工具上,小程序逻辑层的 javascript 代码是运行在 NW.js 中,视图层是由 Chromium 60 Webview 来渲染的 也就是说一切以实物为准,在微信开发者工具上的表现和真机上的表现不尽相同,在真机的不同机器上表现也会因机而异😂 另外由于是寄生在微信上,所以微信又做了一层封装,额外加了一些限制,比如 不支持使用 eval 执行 JS 代码 不支持使用 new Function 创建函数 也就是不让动态执行 JS 代码,说实话,这确实挡住了很多骚操作。正所谓人在屋檐下,不得不低头。鉴于微信提供的巨大流量入口和裂变能力,就这样凑合着用吧😑 上面这些都是各种限制,兼容性问题,当然也有让人开心的地方,那就是CSS3和ES6的特性基本上可以随便用,记住是基本上。 技术栈 众所周知,浏览器的web技术是html,css和js。而小程序虽然类似浏览器,但并不是浏览器。所以他的技术是wxml,wxss和js😂。应该说并没有什么新的技术,就是照抄web标准然后本土化了一下。前端同学基本上可以无缝切入。 我们开发web的时候基本上不会直接去写原生html,css,js,而是使用一些框架和库提升开发效率,例如曾经的jquery,现在的vue,react等。小程序也是如此,通常不会去直接写原生wxml,wxss。当然如果喜欢的话也可以直接去写,但随着项目迭代很快就会难以维护。要知道软件工程的奥义即在于控制复杂性。现在github上已经有了一些不错的框架出来,比如wepy,mpvue。 前端技术 + 小程序官方文档 + 框架文档,基本上这三样就能hold住一个小程序了 说下我的小程序官方文档读后感,不到一个小时读完了简易教程,感觉挺简单的嘛,简直小case。然后去读小程序的框架,组件和api,卧槽,才发现刚才只是读了一本厚书的目录。接下来断断续续看了将近一个月,才勉强看了一遍。哈哈,一切事情都不会像看上去那么简单呐!但如果只是作为入门,不需要很多高级特性,则不需要读那么多章节。 0.3 实际开发 调试预览 工欲善其事,必先利其器。我们开发web时可以随便在某一个你喜欢的浏览器里预览效果,小程序就没那么随意了。因为小程序的宿主是微信,所以小程序只能在微信中才能跑起来。好在微信团队还是挺给力的,为开发者专门开发了一个预览调试工具,即微信开发者工具。修改代码后即可在该工具上实时看到效果,但可是,该工具上呈现的效果并非是真实手机上呈现的效果,就像chrome开发者工具的模拟设备模式一样,虽然八九不离十,但是差之毫厘即谬以千里😂。这个工具上常用且实用的功能还挺多的,建议好好熟悉,文档在此,当然最快熟悉的方式还是点点点,哪里不懂点哪里😁 选个框架 现在的主流框架选择只有wepy和mpvue两位,两者都是向最nb的 Vue.js 看齐。经过仔细斟酌,多方位比对,最终我还是选了wepy,因为发现wepy的星星要比mpvue的多上几个哈哈。wepy文档在此。用了wepy将近一年时间,发现坑还挺多的,可能我对他的期待是像vue一样吧,期待太高了😂。vue稍微高级一点的特性都不支持,有一些实现还和vue是反着来的。不过那还能怎样呢,自己搞一个框架出来?在下实在才薄智浅。曾有一段时间被坑得决心要转向mpvue,但机智的我先去谷歌了一下mpvue的坑,发现相较wepy只多不少,哈哈我赶紧说服自己还是好好和wepy凑合着过吧。 接下来就是写代码开发了,此处直接省略十万字,具体开发的细节就不说了哈,开发-调试-。。。-开发-调试,无限循环,大家都懂的 开发中遇到的坑 【wepy】多次路由到同一个页面时,页面上的变量会相互污染 【wepy】组件是静态组件,导致每实例化一个标签都需要在js的components里声明一次 【wepy】在更新数据之后需要调用[代码]this.$apply()[代码]更新视图,准确的说应该是在异步更新数据之后,也就是说他不是双向绑定 【小程序】文件下载,webview,ajax都需要在小程序管理后台配置安全域名,否则都会失败。 【小程序】webview和h5通信的方式postMessage机制只在特定时机触发,也就是除了这些时机,webview和url完全无法通信 【小程序】web-view中使用input type='file’闪退 小程序的坑可以单独拿出来写一篇千字作文了,有时间再总结一下,此处就不再举例了😂 0.9 提交微信审核 此时功能已经开发测试完毕。接下来就是让用户看到我们辛辛苦苦完成的作品,虽然可能不受待见,甚至被疯狂吐槽,但更大的可能是用户根本不会去访问你的小程序😂,除非你有自己的推广渠道,比如公众号,微博等,否则微信用户纵然数十亿,你的小程序用户却很难破零哈哈。 不管结果怎样,先发布再说。首先需要点击微信开发者工具工具栏的上传按钮上传小程序代码,上传成功后即可前往微信公众平台小程序管理后台去提审你的小程序了,在版本管理里面选择刚才上传的那个版本,然后填写一些信息即可提交审核。首次提交审核通常会等待1~2个工作日,之后迭代版本一般1~2个小时即可过审。 微信审核还是挺严格的,审核规范在此。比较普遍的做法是通过后端接口在提交审核时候过滤敏感内容,以此混过去,等发布到线上之后再把敏感内容放开。哈哈只要思想不滑坡,办法总比困难多。 1.0 发布上线 终于,最后的最后,小程序审核通过了,可以发布到线上了。审核通过之后不会自动发布到线上,需要手动去点发布。发布到线上之后就可以去微信上任何一个入口搜索自己发布的小程序了。 到此可以长舒一口气了,因为已经走完了万里长征的第一步,接下来就是思考怎么去推广和运营小程序,总之,这只是刚刚开始。 最后贴一下自己辛辛苦苦的成果 [图片] 我去看了一下管理后台的访问数据,果然不出所料,用户量至今尚未破零😅
2019-03-01