前端这几年发展太快了,我学习的速度都跟不上演变的速度了(门派太多了,后台都是大牛公司支撑类似于facebook的react、google的angular,angular的1.0还没怎么用过项目,网上查阅2.0的正式版就要出来,书写方法大改,思维架构都有很大的改变,真是难为了现在的前端)。2010年第一次接触前端js,还是从asp.net拖控件中接触,再接着就是我大学那个时代最出名的传智播客视频教学,那个时候课余时间全去看这个视频了,对着教学一个一个的敲,依稀的记得好定义了好多function,现在想想还是很有趣,心想反正就几个方法也不会重复。
Object,Function的prototype时代
随着前端的代码越写越多(自己偶尔会和朋友一起接点外包或帮老师做点项目,毕竟学了不用,永远也只是纸上谈兵),发现自己词穷了,自己定义的function名称太多了(方法重名可是会覆盖之前的方法),这个时候怎么办了,在学校最好一点是什么,就是几乎每个学校都有图书馆,你都能找到自己想要的书籍,因为我本身大学主专业是学习C#的,js这种弱类型语言不停的写function太不美观了(自黑一下,其实我是让人讨人厌的处女座),图书馆有很多js设计模式的书籍,js高级编程,写的都很不错,到现在项目中也都没有完全的用到,有些可能用到了吧,可是都不记得这些专业术语名词(现在什么设计模式,什么新技术的缩写名词太多了,有些虽然用过,可就是就不住。记不住又不行,有些面试官就是喜欢问,不知道你可就惨了,有些更可笑的是考官在网上现查的,然后立即来问你,'哈哈,其实我也做过这种事')。虽然我是一个大懒人可是看多了,至少也是会记住一两个,用Function的prototype和arguments去搞面向对象还是很有趣的,因为是弱类型,所以很多写法更灵活。如果你想说你更懒,那你就Object里面定义一大顿方法也行,其实这种写法在现在也是很流行,比如我们常用的工具类。
闭包时代
好的程序员不是一个人独自敲代码,闭门造车,我们多去查看新技术、新框架、新组建(不过这也确实难为很多人,毕竟互联网是一个多姿多彩的世界。幸好随着时代的进步,我们看书学技术的途径也越来越多了,刚开始我关注过一些有趣技术网站的qq账号,每天都可以在我们逛QQ空间的时候,看到几条很有趣翻译的外国技术分享文章,再后来有朋友推荐我去看各大公司技术论坛网站,不过这个没看多久,太多了,好坏难分,重叠的太多了。移动互联网发展越来越快,微信火得一塌糊涂,几个微信前端公共账号还是不错的,每天都会推荐一篇不错的文章,公共号为’前端早读课‘,’前端大全‘),个人认为好的程序员都应该有拿来主义和创新精神,所以我们引用的框架越来越多,好多框架都是一个js文件,它们都怕自己的代码被污染,所以大多数用到了闭包,那什么是闭包了,闭包有什么好处呢,网上有好多,在这里我也啰嗦几句。
闭包的好处:
1. 逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。
2. 方便调用上下文的局部变量。
3. 加强封装性,第2点的延伸,可以达到对变量的保护作用。
闭包的坏处:
闭包有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生。
优化注意:
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便
只要你搞前端,或者搞web几乎都有人问你,几率几乎达到80%,这个时候推荐一篇博客(深入理解JavaScript系列(2):揭秘命名函数表达式),这可是汤姆大叔,本身非常的佩服他,他写的js设计模式和js注意事项确实不错,就在博客园中,也很感谢这些人在博客园中,我们大学生活才更幸福。
js模块化和MVC
Extjs或sencha touch这两个都是同一家公司的,也是我用到的最早的前端模块化和MVC,sencha touch我用的也是最多的,因为移动端毕竟火爆。
说的它的好处吧:
1.灵活架构,焦点分离
2.方便模块间组合、分解
3.方便单个模块功能调试、升级
4.多人协作互不干扰
mvc是后端说的最多的术语,如果你现在还不懂你最好快点去恶补下,因为现在很多形形色色的前端MVC层出不穷,
MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:
Model(模型)表示应用程序核心(比如数据库记录列表)。
View(视图)显示数据(数据库记录)。
Controller(控制器)处理输入(写入数据库记录)。
MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。
通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。
MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。
啰嗦一点说一下sencha这家js框架公司的好处和弊端吧,他们提供的框架有很好的样式体系,基于sass写的,可以随便我们改变样式风格,提供的sencha.cmd第一次让我感觉到了前端的工程化,提供了代码的压缩、代码验证、代码模块的依赖合并。组件丰富,说了这么多大家感觉一定很爽吧。但是由于他提供非常多的组件,所以导致js代码过多,虽然有些我们可以自行配置筛选压缩,它的依赖压缩不是全部根据配置,大部门和文件夹里面的文件有关,必须不停的移除或添加,反正就是很麻烦,特别是版本的升级时候,真是想吐了。有时因为压缩的缘故还会报一些下错。
AMD和CMD时代
说来前面的大框架我们一定想用到更加轻便的模块框架了,这个时候一定要说说两派的代表框架RequireJS和SeaJs,引用一下github上的专业术语吧,个人也经过一段时间的验证。
相同之处
RequireJS 和 Sea.js 都是模块加载器,倡导模块化开发理念,核心价值是让 JavaScript 的模块化开发变得简单自然。
不同之处
两者的主要区别如下:
-
定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。
-
遵循的规范不同。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不同,导致了两者 API 不同。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
-
推广理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
-
对开发调试的支持有差异。Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。RequireJS 无这方面的明显支持。
-
插件机制不同。RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采取的是通用事件机制,插件类型更丰富。
总之,如果说 RequireJS 是 Prototype 类库的话,则 Sea.js 致力于成为 jQuery 类库。
webpack时代
Seajs我没怎么用过项目,所以也就不说了,RequireJS 用过,那时候用的.net的mvc5.0中的一个第三方插件,帮我省去了很多的配置文件,因为如果我们用nodejs的话一般要自己书写R.js,用来配置一些处理流程,强大的.net插件帮我省去了好多,可是每个模块你都的定义,并且在配置文件中书写出来,每个模块都要写初始模块定义,为什么我会这么去说话一个框架了,因为不断的学习用到了更好的webpack,以下是我的观点(有些解释术语参考了其它博客)
说说一下webpack的优点吧:
1.require.js的所有功能它都有
2.编绎过程更快,因为require.js会去处理不需要的文件
3.还有一个额外的好处就是你不需要再做一个封装的函数,require.js中你得这样
define(['jquery'], function(jquery){})
4.现在你需要一个很大的封装去定义每个模块,然后你需要在在require.js的配制文件中将每个模块的路径都配出来,用过requirejs都会遇到的好繁琐
require.config({ baseUrl: '/scripts', paths: { 'facebook' : '//connect.facebook.net/en_US/all', // 'facebook' : '//connect.facebook.net/en_US/sdk/debug' 'requirejs' : '../bower_components/requirejs/require', 'react' : '../bower_components/react/react-with-addons', 'underscore' : '../bower_components/lodash/dist/lodash', 'futures-requirejs' : '../bower_components/futures-requirejs/future', 'jquery' : '../bower_components/jquery/jquery', // 'phaser' : '../bower_components/phaser/build/phaser', 'phaser.filters' : '../bower_components/phaser/filters/', 'phaser' : '../thirdParty/phaser/Phaser', 'snap' : '../bower_components/Snap.svg/dist/snap.svg', 'proton' : '../thirdParty/Proton', 'copyProperties' : '../thirdParty/copyProperties', 'flux' : '../bower_components/flux/dist/Flux', 'eventEmitter' : '../bower_components/eventEmitter/EventEmitter', 'pixi' : '../bower_components/pixi/bin/pixi', 'crossroads' : '../bower_components/crossroads/dist/crossroads', 'signals' : '../bower_components/js-signals/dist/signals', 'hasher' : '../bower_components/hasher/dist/js/hasher', 'async' : '../bower_components/async/lib/async', 'socket.io-client' : '../bower_components/socket.io-client/dist/socket.io', 'html2canvas' : '../bower_components/html2canvas/build/html2canvas.min', 'hammer' : '../bower_components/hammerjs/hammer', 'touch-emulator' : '../bower_components/hammer-touchemulator/touch-emulator', 'moment' : '../bower_components/moment/moment', // 'famous' : '../bower_components/famous', 'tinygradient' : '../bower_components/tinygradient/tinygradient', 'page' : '../bower_components/page/index', // 'faker' : '../bower_components/faker/dist/faker', 'faker' : '../thirdParty/Faker', 'perlin' : '../thirdParty/Perlin', 'tinycolor' : '../vendors/tinycolor', // 'flux' : '../../node_modules/flux/index', 'client' : './', 'errors' : './errors', 'server' : '../../server', }, packages: [{ name : 'API2', location : '../bower_components/api2/src/', main : 'API' }], shim: { 'phaser.filters/Fire': { deps: ['phaser'], }, 'page': { exports: 'page' }, 'snap' : { exports: 'Snap' }, 'html2canvas' : { exports: 'html2canvas' }, 'facebook' : { exports: 'FB' }, // 'underscore': { // deps: [], // exports: '_' // }, 'phaser': { exports: 'Phaser' }, 'pixi': { exports: 'PIXI' }, 'hammer': { exports: 'Hammer' }, 'touch-emulator': { exports: 'TouchEmulator' }, 'proton': { exports: 'Proton' }, 'moment': { exports: 'moment' } } });