发现都是正则表达式式,研究了几天差点想砸电脑

&p&看了一下这种瀑布流&b&码蜂社公开课520特别期&/b&曾经分享过,&b&Flex布局零JS实现的&/b&你信么?&/p&&p&效果图如下:&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-c882e1b6dd6d1b12c796360_b.jpg& data-rawwidth=&1036& data-rawheight=&966& class=&origin_image zh-lightbox-thumb& width=&1036& data-original=&https://pic3.zhimg.com/50/v2-c882e1b6dd6d1b12c796360_r.jpg&&&/figure&&p&效果链接:&a href=&//link.zhihu.com/?target=https%3A//mfs-mark.github.io/love-wall/one-height.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&love&/a&&/p&&p&公开课视频在此 &a href=&//link.zhihu.com/?target=http%3A//bbs.mafengshe.com/topic/64/-%25E6%25AF%258D%25E4%25BA%25B2%25E8%258A%E4%25B8%%25A2%%259B%25BE%25E7%E5%25A2%2599& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&-母亲节&520专题-图片墙&/a& &/p&&p&码蜂社公开课信息在&a href=&https://zhuanlan.zhihu.com/fe-guide& class=&internal&&前端指南&/a& 发布,如果有帮助欢迎关注~&/p&
看了一下这种瀑布流码蜂社公开课520特别期曾经分享过,Flex布局零JS实现的你信么?效果图如下:效果链接:公开课视频在此
码蜂社公开课信息在 发布,如果有帮助欢迎关注~
&b&通常情况下我们都会从求职者的角度去考虑面试求职这件事,但是如果换个角度,从面试官的角度来看这件事呢?如何从面试官的角度来准备好一场面试呢?本文只针对初级前端或者没有工作经验的应届毕业生。&/b&&br&&p&大部分人在求职的时候,通常是这样的流程:&br&写简历-&网上找企业投简历-&收到面试通知,准备-&面试。这整个过程中,还包含着准备面试的阶段。关于如何准备面试不是本文探讨的内容,这篇文章是想从面试官或者企业的角度出发,尝试从招聘方理解他们会如何去面试一个求职者这个角度来帮助我们更好的准备面试,从而得到自己心仪的offer(本文只针对it行业,或者再缩小范围,只针对前端招聘)。&br&ps:只所以想写这篇文章,是因为之前招的前端由于各种原因被辞退了,所以这段时间又开始在招聘初级前端工程师。从之前的面试者到面试官的身份转换,这个过程产生了一些想法,所以就把这些想法记录下来,也算是为以后自己的求职做准备。&/p&面试官是如何面试求职者&p&其实我也还是属于入门一年多的前端,并没有太多经验和能力来面试别人,尤其是在面试和招聘这两个方面。但是这并不妨碍你去学习。我网上找过资料,询问过公司的大神,也向公司负责人事的总经理请教过。这篇文章其实就是基于这几方面收集的整合。&br&&strong&一般企业会从下面几个方面来考察面试者&/strong&&/p&&ol&&li&考察对方专业知识,根据对方的回答再进行深入提问。考察专业知识这点已经是共识了。只有专业知识符合了,才能有机会进行下面的面试阶段。&/li&&li&询问对方感兴趣的技术是什么(技术方面),然后根据他所说的技术,深入挖掘问下去。因为在面试官看来,如果你连感兴趣的东西都了解得不多,学得不够好,不是态度的问题就是学习能力的问题。而这两者都是企业不愿意在一个员工身上看到的。&/li&&li&询问对方的做项目中遇到什么样的难题,怎么解决的?每个人在做项目的时候都会遇到难题,但是如果你没有记录总结的习惯,你就不太可能在这个环节回答得很好。&/li&&li&询问对方平时遇到问题都是如何解决的或者抛出一个问题让对方给出解决方案或者思路。从对方的回答中来判断对方解决问题的思路和方法。&/li&&li&询问对方下班后的时间都会花在什么地方?从对方的回答中判断对方是否会主动学习,毕竟程序员这个行业是需要保持不断学习的步伐才能不落后。当然了这个问题是需要有提问技巧的,如果这么直白得问,求职者的回答肯定都是套路。&/li&&li&在沟通的过程观察对方的表达能力。 如果是表达能力存在比较大的问题,则可能会给后面的工作造成困扰,因为你在公司不是一个人在战斗,肯定是需要同事的沟通与协作。能把意思表达清楚是一个必须要掌握的能力。&/li&&li&谈到薪资的过程,可通过公司提供的成长性、技术成长等方面来平衡对方的心理落差。这点是总经理说的,HR总是想着法子将你的工资压下来(一脸鄙视)。&/li&&/ol&求职者如何准备面试&p&有了这几个参考的角度,是不是就会觉得准备面试就没有那么无从下手了。那我们就看针对上面说的一点一点来看如何应对&/p&&b&一、专业知识&/b&&p&这部分的内容就好像上学时代考卷中的选择题和填空题。前端基本专业知识就那些,你看或不看,它都在那里。这部分就没有太多技巧可言了,好好找几份前端面试题,该背得背,该coding得还是老老实实地coding。这里附上两份github的面试题大全:&/p&&ul&&li&&a href=&//link.zhihu.com/?target=https%3A//github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&My-blog/Front-end-Developer-Questions at master · markyun/My-blog · GitHub&/a&&/li&&li&&a href=&//link.zhihu.com/?target=https%3A//github.com/h5bp/Front-end-Developer-Interview-Questions/tree/master/Translations/Chinese& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Front-end-Developer-Interview-Questions/Translations/Chinese at master · h5bp/Front-end-Developer-Interview-Questions · GitHub&/a&&/li&&/ul&&b&二、感兴趣的技术&/b&&p&如果把整个面试过程看做一场考试,第一部分是封闭型问题,那么这部分则是开放性问题,没有标准可言。&br&但是有一点一定要注意的:&strong&所说的技术一定是你最熟悉的&/strong&,因为对于你感兴趣的技术,面试官一定不会放过这个机会,深入问下去的。&br&可能会有人会觉得,感兴趣的技术为什么非得是你熟练掌握的技术呢?我对一项新的技术很感兴趣,但是我还没有来得及深入学习。这样的想法也是正确的,在平常的回答中,你大可以这么说。但这是在面试啊,你需要在跟面试官的沟通过程中,让对方更多的了解到你。所以如果你这么回答:“我对这项技术很感兴趣,但是我还不懂这项技术”,目测面试官会一脸懵逼,这还能不能愉快得沟通啊。这简直就是面试话题终结者。因为在面试官看来,如果你连喜欢的东西都研究得不够深入,那么你所谓的喜欢也太廉价了。&br&这就回到了面试的目的。面试的目的不是让你百分百的表达你的真实想法,而是让你尽可能得在整个面试过程中,让对方能更全面得了解到你的能力。任何行为和言语如果不能达到这个目的,都应该尽量减少或者避免。&/p&&b&三、做项目过程遇到什么难以解决的难题?最后如何解决&/b&&p&这个问题我问过很多应届毕业生,屡试不爽。普遍的回答都是没有什么问题。没有问题本身就是最大的问题。试想下,你在做任何东西的过程中怎么可能没有问题呢?比如你在利用新框架做一个项目,那么关于环境的搭建是否有疑问?关于新框架语法是否有疑问?还有每个框架都会存在很多坑,你没有踩过吗?还有作为web开发者,PC的浏览器兼容问题有遇到过吗?Android和iOS兼容性问题?这些都是你在做项目过程中可能会遇到的问题,如果你就这么回答没有,则一定说明你没有深入思考过或者遇到问题从来不会记录和总结。&/p&&p&&strong&那么对于这个问题该如何准备呢&/strong&&br&其实如果有记录和总结问题的习惯的话,那么这个问题就迎刃而解。如果没有的话,那就从现在开始培养这个习惯咯。可以每天建立一个问题记录列表,用来收集每天的问题(模板如下):&br&&/p&&div class=&highlight&&&pre&&code class=&language-bash&&&span class=&c&&# 问题描述:&/span&
gulp执行sass命令报错
node_modules/node-sass/vendor/darwin-x64-48/binding.node,
是node-sass的问题,rebuild即可
npm rebuild node-sass
&/code&&/pre&&/div&&p&通过每日记录问题来培养这种习惯。这个方法也可以用在做项目的过程中,专门为每个项目建一个&strong&问题记录列表&/strong&,所有在项目开发过程中遇到的问题,都可以扔到这个列表中,然后再按照上面的方法,将问题描述和解决办法补齐。最后在项目结束后,就可以通过这份问题记录列表来做总结。&br&这样就不用再担心在这个问题回答不出来了,就把你问题记录列表里的内容抛出来就行。&/p&&b&四、询问对方平时遇到问题都是如何解决&/b&&p&工作中最重要的能力应当是解决问题的能力。解决问题的能力包括思路和能力两部分。思路就是你想到如何去解决这个问题,而能力就是指具体解决问题的能力,这里指coding能力。所以在遇到问题的时候,如何清晰地将你解决问题的思路表达出来就显得很重要了。思路这种东西,就是你脑袋中的各种想法,如果你没有刻意得训练过,很难一下子将其通过语言清楚得表达出来。所以要想回答好这个问题,也需要在平常的学习和工作过程中,有意识地&strong&将解决问题的想法通过文字或者流程图、思维导图等方式记录下来&/strong&。这样的训练过程能强化解决问题的思路,对解决问题也是很有帮助的。&/p&&b&五、询问对方下班后的时间都会花在什么地方?&/b&&p&这个问题意图太明显了,所以大部分面试者的回答都是套路,不够具体且没有可信度。比如:“下班后一般就看书、学习”这类的回答。讲真的,如果你从无数个面试者口中听到类似的话,那么你可能就不会再相信这句话了。这类问题的回答就跟制定计划很类似,如果你制定的计划非常模糊:我要学习Vuejs,那多半这个计划就会执行不下去了。但如果你制定的计划是这样的:&/p&&div class=&highlight&&&pre&&code class=&language-text&&学习计划:掌握vuejs,能独立完成vuejs的项目
具体行动:
1、官网学习vuejs api
2、使用vuejs完成TODO sample
3、使用vue-cli脚手架构建项目
4、学习vue-router的使用
5、学习vue-resource使用
6、做一个XXX项目
&/code&&/pre&&/div&&p&那么这个计划就相对完成的概率就高很多。&br&同样地,如果你的回答是具体且可实施的,那么可信度就会大大增加了。对于这个问题,我的回答会是这样的:&/p&&div class=&highlight&&&pre&&code class=&language-text&&正常情况下是6点下班,除去通勤和吃饭及休息时间,一般8点半开始空闲出来。
1、首先,我会选择先花20分钟到30分钟跟着健身App锻炼,即保持健康,也为了保证后续学习的精神状态。
2、接着便是学习、看书和coding time。在奇妙清单中,我建有“学习计划”,“阅读计划”,“项目计划”三个清单。
一般是会先花半个小时在阅读计划上。半个小时结束之后,再根据学习计划和项目计划来安排。
比如这两天的时间用来完成项目计划中的任务,然后后面几天就可以用来学习,完成学习计划中的任务。
&/code&&/pre&&/div&&p&相信这样回答的可信度肯定拉“下班后一般就看书、学习”这种回答好几条街。&br&&strong&当然了,这么回答的前提是你真的有这么在做,我可没有教你虚造这样的回答。&/strong&&/p&&b&六、关于表达能力&/b&&p&关于如何提高表达能力,网上已经有太多的资源和教程了。我只能帮你到这,剩下的就靠你自己了。&br&再多说一句,以程序员这个行业对表达能力的要求远没有其他行业如销售那般高,只要你能把意思简洁明了地表达清楚就可以了。如果当中能再多点风趣幽默,那简直就是完美了。&/p&&p&&b&七:关于薪资&/b&&/p&&p&关于如何谈薪资,可以参考之前写过文章:&a href=&//link.zhihu.com/?target=http%3A//www.iamsuperman.cn//interview/how-to-deal-with-hr/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&iamsuperman.cn/2016/08/&/span&&span class=&invisible&&02/interview/how-to-deal-with-hr/&/span&&span class=&ellipsis&&&/span&&/a&&br&总之一句话,合理认识你的价值,不要被HR的话所吓倒了。该要多少钱,就要多少,不要慌!&/p&
通常情况下我们都会从求职者的角度去考虑面试求职这件事,但是如果换个角度,从面试官的角度来看这件事呢?如何从面试官的角度来准备好一场面试呢?本文只针对初级前端或者没有工作经验的应届毕业生。 大部分人在求职的时候,通常是这样的流程: 写简历-&网…
HTML+CSS&br&
1.对WEB标准以及W3C的理解与认识&br&
标签闭合、标签小写、不乱嵌套、提高搜索机器人搜索几率、使用外
链css和js脚本、结构行为表现的分离、文件下载与页面速度更快、内容能被更多的用户所访问、内容能被更广泛的设备所访问、更少的代码和组件,容易维
护、改版方便,不需要变动页面内容、提供打印版本而不需要复制内容、提高网站易用性;&br&&br&
2.xhtml和html有什么区别&br&
HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的置标语言&br&
最主要的不同:&br&
XHTML 元素必须被正确地嵌套。&br&
XHTML 元素必须被关闭。&br&
标签名必须用小写字母。&br&
XHTML 文档必须拥有根元素。&br&&br&
3.Doctype? 严格模式与混杂模式-如何触发这两种模式,区分它们有何意义?&br&
用于声明文档使用那种规范(html/Xhtml)一般为 严格 过度 基于框架的html文档&br&
加入XMl声明可触发,解析方式更改为IE5.5 拥有IE5.5的bug&br&&br&
4.行内元素有哪些?块级元素有哪些?CSS的盒模型?&br&
块级元素:div p h1 h2 h3 h4 form ul&br&
行内元素: a b br i span input select&br&
Css盒模型:内容,border ,margin,padding&br&&br&
5.CSS引入的方式有哪些? link和@import的区别是?&br&
内联 内嵌 外链 导入&br&
区别 :同时加载&br&
前者无兼容性,后者CSS2.1以下浏览器不支持&br&
Link 支持使用javascript改变样式,后者不可&br&&br&
6.CSS选择符有哪些?哪些属性可以继承?优先级算法如何计算?内联和important哪个优先级高?&br&
标签选择符 类选择符 id选择符&br&
继承不如指定 Id&class&标签选择&br&
后者优先级高&br&&br&
7.前端页面有哪三层构成,分别是什么?作用是什么?&br&
结构层 Html 表示层 CSS 行为层 js&br&&br&
8.css的基本语句构成是?&br&
选择器{属性1:值1;属性2:值2;……}&br&&br&
9.你做的页面在哪些流览器测试过?这些浏览器的内核分别是什么?&br&
Ie(Ie内核) 火狐(Gecko) 谷歌(webkit) opear(Presto)&br&&br&
10.写出几种IE6 BUG的解决方法&br&
1.双边距BUG float引起的 使用display&br&
2.3像素问题 使用float引起的 使用dislpay:inline -3px&br&
3.超链接hover 点击后失效 使用正确的书写顺序 link visited hover active&br&
4.Ie z-index问题 给父级添加position:relative&br&
5.Png 透明 使用js代码 改&br&
6.Min-height 最小高度 !Important 解决’&br&
7.select 在ie6下遮盖 使用iframe嵌套&br&
8.为什么没有办法定义1px左右的宽度容器(IE6默认的行高造成的,使用over:hidden,zoom:0.08 line-height:1px)&br&&br&
11.标签上title与alt属性的区别是什么?&br&
Alt 当图片不显示是 用文字代表。&br&
Title 为该属性提供信息&br&&br&
12.描述css reset的作用和用途。&br&
Reset重置浏览器的css默认属性 浏览器的品种不同,样式不同,然后重置,让他们统一&br&&br&
13.解释css sprites,如何使用。&br&
Css 精灵 把一堆小的图片整合到一张大的图片上,减轻服务器对图片的请求数量&br&&br&
14.浏览器标准模式和怪异模式之间的区别是什么?&br&
盒子模型 渲染模式的不同&br&
使用 window.top.document.compatMode 可显示为什么模式&br&&br&
15.你如何对网站的文件和资源进行优化?期待的解决方案包括:&br&
文件合并&br&
文件最小化/文件压缩&br&
使用CDN托管&br&
缓存的使用&br&&br&
16.什么是语义化的HTML?&br&
直观的认识标签 对于搜索引擎的抓取有好处&br&&br&
17.清除浮动的几种方式,各自的优缺点&br&
1.使用空标签清除浮动 clear:both(理论上能清楚任何标签,,,增加无意义的标签)&br&
2.使用overflow:auto(空标签元素清除浮动而不得不增加无意代码的弊端,,使用zoom:1用于兼容IE)&br&
3.是用afert伪元素清除浮动(用于非IE浏览器)&br&&br&
Javascript&br&
1.javascript的typeof返回哪些数据类型&br&
Object number function boolean underfind&br&&br&
2.例举3种强制类型转换和2种隐式类型转换?&br&
强制(parseInt,parseFloat,number)&br&
隐式(== – ===)&br&&br&
3.split() join() 的区别&br&
前者是切割成数组的形式,后者是将数组转换成字符串&br&&br&
4.数组方法pop() push() unshift() shift()&br&
Push()尾部添加 pop()尾部删除&br&
Unshift()头部添加 shift()头部删除&br&&br&
5.事件绑定和普通事件有什么区别&br&&br&
6.IE和DOM事件流的区别&br&
1.执行顺序不一样、&br&
2.参数不一样&br&
3.事件加不加on&br&
4.this指向问题&br&&br&
7.IE和标准下有哪些兼容性的写法&br&
Var ev = ev || window.event&br&
document.documentElement.clientWidth || document.body.clientWidth&br&
Var target = ev.srcElement||ev.target&br&&br&
8.ajax请求的时候get 和post方式的区别&br&
一个在url后面 一个放在虚拟载体里面&br&
有大小限制&br&
安全问题&br&
应用不同 一个是论坛等只需要请求的,一个是类似修改密码的&br&&br&
9.call和apply的区别&br&
Object.call(this,obj1,obj2,obj3)&br&
Object.apply(this,arguments)&br&&br&
10.ajax请求时,如何解释json数据&br&
使用eval parse 鉴于安全性考虑 使用parse更靠谱&br&
11.b继承a的方法&br&&br&
12.写一个获取非行间样式的函数&br&&br&
function getStyle(obj,attr,value)&br&
if(!value)&br&
if(obj.currentStyle)&br&
return obj.currentStyle(attr)&br&
obj.getComputedStyle(attr,false)&br&
obj.style[attr]=value&br&
13.事件委托是什么&br&
让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行!&br&&a href=&//link.zhihu.com/?target=http%3A//www.webasily.com/%3Fp%3D78& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&webasily.com/?&/span&&span class=&invisible&&p=78&/span&&span class=&ellipsis&&&/span&&/a& 例子可见此链接&br&&br&
14.闭包是什么,有什么特性,对页面有什么影响&br&
闭包就是能够读取其他函数内部变量的函数。&br&&a href=&//link.zhihu.com/?target=http%3A//blog.csdn.net/gaoshanwudi/article/details/7355794& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&深入理解JavaScript的闭包特性 如何给循环中的对象添加事件&/a& 此链接可查看(问这个问题的不是一个公司)&br&&br&
15.如何阻止事件冒泡和默认事件&br&
canceBubble return false&br&&br&
16.添加 删除 替换 插入到某个接点的方法&br&
obj.appendChidl()&br&
obj.innersetBefore&br&
obj.replaceChild&br&
obj.removeChild&br&&br&
17.解释jsonp的原理,以及为什么不是真正的ajax&br&
动态创建script标签,回调函数&br&
Ajax是页面无刷新请求数据操作&br&&br&
18.javascript的本地对象,内置对象和宿主对象&br&
本地对象为array obj regexp等可以new实例化&br&
内置对象为gload Math 等不可以实例化的&br&
宿主为浏览器自带的document,window 等&br&&br&
19.document load 和document ready的区别&br&
Document.onload 是在结构和样式加载完才执行js&br&
Document.ready原生种没有这个方法,jquery中有 $().ready(function)&br&&br&
20.”==”和“===”的不同&br&
前者会自动转换类型&br&
后者不会&br&&br&
21.javascript的同源策略&br&
一段脚本只能读取来自于同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议和端口号的组合&br&&br&
22.编写一个数组去重的方法&br&
function oSort(arr)&br&
var result ={};&br&
var newArr=[];&br&
for(var i=0;i&arr.i++)&br&
if(!result[arr])&br&
newArr.push(arr)&br&
result[arr]=1&br&
return newArr&br&
·欢迎添加我微信:agoodjob11&br&&a href=&//link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzAwNjA3NDMyOA%3D%3D%26mid%3Didx%3D1%26sn%3D7c941b8d7b4aaa378b59d34%23rd& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&邀请你加入群聊,程序源·微吧。&/a&
1.对WEB标准以及W3C的理解与认识
标签闭合、标签小写、不乱嵌套、提高搜索机器人搜索几率、使用外
链css和js脚本、结构行为表现的分离、文件下载与页面速度更快、内容能被更多的用户所访问、内容能被更广泛的设备所访问、更少的代码和组件,容…
&figure&&img src=&https://pic1.zhimg.com/v2-41aafc2b10fa1_b.jpg& data-rawwidth=&1280& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic1.zhimg.com/v2-41aafc2b10fa1_r.jpg&&&/figure&&blockquote&&p&共 5024 字,读完需 6 分钟,速读需 2 分钟,本文首发于知乎专栏&a href=&https://zhuanlan.zhihu.com/feweekly& class=&internal&&前端周刊&/a&。写在前面,笔者在做面试官这 2 年多的时间内,面试了数百个前端工程师,惊讶的发现,超过 80% 的候选人对下面这道题的回答情况连及格都达不到。这究竟是怎样神奇的一道面试题?他考察了候选人的哪些能力?对正在读本文的你有什么启示?且听我慢慢道来&/p&&/blockquote&&h2&不起眼的开始&/h2&&p&招聘前端工程师,尤其是中高级前端工程师,扎实的 JS 基础绝对是必要条件,基础不扎实的工程师在面对前端开发中的各种问题时大概率会束手无策。在考察候选人 JS 基础的时候,我经常会提供下面这段代码,然后让候选人分析它实际运行的结果:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&var&/span& &span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&&/span& &span class=&mi&&5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&&p&这段代码很短,只有 7 行,我想,能读到这里的同学应该不需要我逐行解释这段代码在做什么吧。候选人面对这段代码时给出的结果也不尽相同,以下是典型的答案:&/p&&ul&&li&A. 20% 的人会快速扫描代码,然后给出结果:0,1,2,3,4,5;&/li&&li&B. 30% 的人会拿着代码逐行看,然后给出结果:5,0,1,2,3,4;&/li&&li&C. 50% 的人会拿着代码仔细琢磨,然后给出结果:5,5,5,5,5,5;&/li&&/ul&&p&只要你对 JS 中同步和异步代码的区别、变量作用域、闭包等概念有正确的理解,就知道正确答案是 C,代码的实际输出是:&/p&&div class=&highlight&&&pre&&code class=&language-bash&&&span&&/span&T00:43:45.873Z 5
T00:43:46.866Z 5
T00:43:46.868Z 5
T00:43:46.868Z 5
T00:43:46.868Z 5
T00:43:46.868Z 5
&/code&&/pre&&/div&&p&接下来我会追问:如果我们约定,用箭头表示其前后的两次输出之间有 1 秒的时间间隔,而逗号表示其前后的两次输出之间的时间间隔可以忽略,代码实际运行的结果该如何描述?会有下面两种答案:&/p&&ul&&li&A. 60% 的人会描述为:5 -& 5 -& 5 -& 5 -& 5,即每个 5 之间都有 1 秒的时间间隔;&/li&&li&B. 40% 的人会描述为:5 -& 5,5,5,5,5,即第 1 个 5 直接输出,1 秒之后,输出 5 个 5;&/li&&/ul&&p&这就要求候选人对 JS 中的&a href=&http://link.zhihu.com/?target=http%3A//ejohn.org/blog/how-javascript-timers-work/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&定时器工作机制&/a&非常熟悉,循环执行过程中,几乎同时设置了 5 个定时器,一般情况下,这些定时器都会在 1 秒之后触发,而循环完的输出是立即执行的,显而易见,正确的描述是 B。&/p&&p&如果到这里算是及格的话,100 个人参加面试只有 20 人能及格,读到这里的同学可以仔细思考,你及格了么?&/p&&h2&追问 1:闭包&/h2&&p&如果这道题仅仅是考察候选人对 JS 异步代码、变量作用域的理解,局限性未免太大,接下来我会追问,如果期望代码的输出变成:5 -& 0,1,2,3,4,该怎么改造代码?熟悉闭包的同学很快能给出下面的解决办法:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&var&/span& &span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&&/span& &span class=&mi&&5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&j&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// j = i&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&j&/span&&span class=&p&&);&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span&&span class=&p&&);&/span&
&span class=&p&&})(&/span&&span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&&p&巧妙的利用 &a href=&http://link.zhihu.com/?target=http%3A//benalman.com/news/2010/11/immediately-invoked-function-expression/%23iife& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IIFE&/a&(Immediately Invoked Function Expression:声明即执行的函数表达式)来解决闭包造成的问题,确实是不错的思路,但是初学者可能并不觉得这样的代码很好懂,至少笔者初入门的时候这里琢磨了一会儿才真正理解。&/p&&p&有没有更符合直觉的做法?答案是有,我们只需要对循环体稍做手脚,让负责输出的那段代码能拿到每次循环的 i 值即可。该怎么做呢?利用 JS 中基本类型(Primitive Type)的参数传递是&a href=&http://link.zhihu.com/?target=http%3A//stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&按值传递&/a&(Pass by Value)的特征,不难改造出下面的代码:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&output&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span& &span class=&p&&(&/span&&span class=&nx&&i&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span&&span class=&p&&);&/span&
&span class=&p&&};&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&var&/span& &span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&&/span& &span class=&mi&&5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&output&/span&&span class=&p&&(&/span&&span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&c1&&// 这里传过去的 i 值被复制了&/span&
&span class=&p&&}&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&&p&能给出上述 2 种解决方案的候选人可以认为对 JS 基础的理解和运用是不错的,可以各加 10 分。当然实际面试中还有候选人给出如下的代码:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&for (let i = 0; i & 5; i++) {
setTimeout(function() {
console.log(new Date, i);
console.log(new Date, i);
&/code&&/pre&&/div&&p&细心的同学会发现,这里只有个非常细微的变动,即使用 ES6 &a href=&http://link.zhihu.com/?target=https%3A//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&块级作用域&/a&(Block Scope)中的 let 替代了 var,但是代码在实际运行时会报错,因为最后那个输出使用的 i 在其所在的作用域中并不存在,i 只存在于循环内部。&/p&&p&能想到 ES6 特性的同学虽然没有答对,但是展示了自己对 ES6 的了解,可以加 5 分,继续进行下面的追问。&/p&&h2&追问 2:ES6&/h2&&p&有经验的前端同学读到这里可能有些不耐烦了,扯了这么多,都是他知道的内容,先别着急,挑战的难度会继续增加。&/p&&p&接着上文继续追问:如果期望代码的输出变成 0 -& 1 -& 2 -& 3 -& 4 -& 5,并且要求原有的代码块中的循环和两处 console.log 不变,该怎么改造代码?新的需求可以精确的描述为:代码执行时,立即输出 0,之后每隔 1 秒依次输出 1,2,3,4,循环结束后在大概第 5 秒的时候输出 5(这里使用大概,是为了避免钻牛角尖的同学陷进去,因为 JS 中的定时器触发时机有可能是不确定的,具体可参见 &a href=&http://link.zhihu.com/?target=http%3A//ejohn.org/blog/how-javascript-timers-work/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&How Javascript Timers Work&/a&)。&/p&&p&看到这里,部分同学会给出下面的可行解:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&var&/span& &span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&&/span& &span class=&mi&&5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&j&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&j&/span&&span class=&p&&);&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span& &span class=&o&&*&/span& &span class=&nx&&j&/span&&span class=&p&&));&/span&
&span class=&c1&&// 这里修改 0~4 的定时器时间&/span&
&span class=&p&&})(&/span&&span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span& &span class=&c1&&// 这里增加定时器,超时设置为 5 秒&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span& &span class=&o&&*&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&&p&不得不承认,这种做法虽粗暴有效,但是不算是能额外加分的方案。如果把这次的需求抽象为:在系列异步操作完成(每次循环都产生了 1 个异步操作)之后,再做其他的事情,代码该怎么组织?聪明的你是不是想起了什么?对,就是 &a href=&http://link.zhihu.com/?target=https%3A//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Promise&/a&。&/p&&p&可能有的同学会问,不就是在控制台输出几个数字么?至于这样杀鸡用牛刀?你要知道,面试官真正想考察的是候选人是否具备某种能力和素质,因为在现代的前端开发中,处理异步的代码随处可见,熟悉和掌握异步操作的流程控制是成为合格开发者的基本功。&/p&&p&顺着下来,不难给出基于 Promise 的解决方案(既然 Promise 是 ES6 中的新特性,我们的新代码使用 ES6 编写是不是会更好?如果你这么写了,大概率会让面试官心生好感):&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&const&/span& &span class=&nx&&tasks&/span& &span class=&o&&=&/span& &span class=&p&&[];&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&var&/span& &span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&&/span& &span class=&mi&&5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// 这里 i 的声明不能改成 let,如果要改该怎么做?&/span&
&span class=&p&&((&/span&&span class=&nx&&j&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&tasks&/span&&span class=&p&&.&/span&&span class=&nx&&push&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Promise&/span&&span class=&p&&((&/span&&span class=&nx&&resolve&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&j&/span&&span class=&p&&);&/span&
&span class=&nx&&resolve&/span&&span class=&p&&();&/span&
&span class=&c1&&// 这里一定要 resolve,否则代码不会按预期 work&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span& &span class=&o&&*&/span& &span class=&nx&&j&/span&&span class=&p&&);&/span&
&span class=&c1&&// 定时器的超时时间逐步增加&/span&
&span class=&p&&}));&/span&
&span class=&p&&})(&/span&&span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&nb&&Promise&/span&&span class=&p&&.&/span&&span class=&nx&&all&/span&&span class=&p&&(&/span&&span class=&nx&&tasks&/span&&span class=&p&&).&/span&&span class=&nx&&then&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span&&span class=&p&&);&/span&
&span class=&c1&&// 注意这里只需要把超时设置为 1 秒&/span&
&span class=&p&&});&/span&
&/code&&/pre&&/div&&p&相比而言,笔者更倾向于下面这样看起来更简洁的代码,要知道编程风格也是很多面试官重点考察的点,代码阅读时的颗粒度更小,模块化更好,无疑会是加分点。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&const&/span& &span class=&nx&&tasks&/span& &span class=&o&&=&/span& &span class=&p&&[];&/span& &span class=&c1&&// 这里存放异步操作的 Promise&/span&
&span class=&kr&&const&/span& &span class=&nx&&output&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&&span class=&nx&&i&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&k&&new&/span& &span class=&nb&&Promise&/span&&span class=&p&&((&/span&&span class=&nx&&resolve&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&nx&&resolve&/span&&span class=&p&&();&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span& &span class=&o&&*&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&});&/span&
&span class=&c1&&// 生成全部的异步操作&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&var&/span& &span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&&/span& &span class=&mi&&5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&tasks&/span&&span class=&p&&.&/span&&span class=&nx&&push&/span&&span class=&p&&(&/span&&span class=&nx&&output&/span&&span class=&p&&(&/span&&span class=&nx&&i&/span&&span class=&p&&));&/span&
&span class=&p&&}&/span&
&span class=&c1&&// 异步操作完成之后,输出最后的 i&/span&
&span class=&nb&&Promise&/span&&span class=&p&&.&/span&&span class=&nx&&all&/span&&span class=&p&&(&/span&&span class=&nx&&tasks&/span&&span class=&p&&).&/span&&span class=&nx&&then&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&},&/span& &span class=&mi&&1000&/span&&span class=&p&&);&/span&
&span class=&p&&});&/span&
&/code&&/pre&&/div&&p&读到这里的同学,恭喜你,你下次面试遇到类似的问题,至少能拿到 80 分。&/p&&p&我们都知道使用 Promise 处理异步代码比回调机制让代码可读性更高,但是使用 Promise 的问题也很明显,即如果没有处理 Promise 的 reject,会导致错误被&a href=&http://link.zhihu.com/?target=http%3A//blog.rangle.io/errors-in-promises/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&丢进黑洞&/a&,好在新版的 Chrome 和 Node 7.x 能对未处理的异常给出 &a href=&http://link.zhihu.com/?target=https%3A//nodejs.org/api/process.html%23process_event_unhandledrejection& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Unhandled Rejection Warning&/a&,而排查这些错误还需要一些特别的技巧(&a href=&http://link.zhihu.com/?target=https%3A//www.bennadel.com/blog/3239-logging-and-debugging-unhandled-promise-rejections-in-the-browser.htm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&浏览器&/a&、&a href=&http://link.zhihu.com/?target=https%3A//www.bennadel.com/blog/3238-logging-and-debugging-unhandled-promise-rejections-in-node-js-v1-4-1-and-later.htm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Node.js&/a&)。&/p&&h2&追问 3:ES7&/h2&&p&既然你都看到这里了,那就再坚持 2 分钟,接下来的内容会让你明白你的坚持是值得的。&/p&&p&多数面试官在决定聘用某个候选人之前还需要考察另外一项重要能力,即技术自驱力,直白的说就是候选人像有内部的马达在驱动他,用漂亮的方式解决工程领域的问题,不断的跟随业务和技术变得越来越牛逼,究竟什么是牛逼?建议阅读程序人生的&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&这篇剖析&/a&。&/p&&p&回到正题,既然 Promise 已经被拿下,如何使用 ES7 中的 async await 特性来让这段代码变的更简洁?你是否能够根据自己目前掌握的知识给出答案?请在这里暂停 1 分钟,思考下。&/p&&p&下面是笔者给出的参考代码:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// 模拟其他语言中的 sleep,实际上可以是任何异步操作&/span&
&span class=&kr&&const&/span& &span class=&nx&&sleep&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&&span class=&nx&&timeountMS&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&k&&new&/span& &span class=&nb&&Promise&/span&&span class=&p&&((&/span&&span class=&nx&&resolve&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&setTimeout&/span&&span class=&p&&(&/span&&span class=&nx&&resolve&/span&&span class=&p&&,&/span& &span class=&nx&&timeountMS&/span&&span class=&p&&);&/span&
&span class=&p&&});&/span&
&span class=&p&&(&/span&&span class=&nx&&async&/span& &span class=&p&&()&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&c1&&// 声明即执行的 async 函数表达式&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&var&/span& &span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&&/span& &span class=&mi&&5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&await&/span& &span class=&nx&&sleep&/span&&span class=&p&&(&/span&&span class=&mi&&1000&/span&&span class=&p&&);&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&nx&&await&/span& &span class=&nx&&sleep&/span&&span class=&p&&(&/span&&span class=&mi&&1000&/span&&span class=&p&&);&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&);&/span&
&span class=&p&&})();&/span&
&/code&&/pre&&/div&&h2&总结&/h2&&p&感谢你花时间读到这里,相信你收获的不仅仅是用 JS 精确控制代码输出的各种技巧,更是对于前端工程师的成长期许:扎实的语言基础、与时俱进的能力、强大技术自驱力。&/p&&h2&One More Thing&/h2&&p&本文作者王仕军,商业转载请联系作者获得授权,非商业转载请注明出处。如果你觉得本文对你有帮助,请点赞!如果对文中的内容有任何疑问,欢迎留言讨论。想知道我接下来会写些什么?欢迎订阅知乎专栏:&a href=&https://zhuanlan.zhihu.com/feweekly& class=&internal&&《前端周刊:让你在前端领域跟上时代的脚步》&/a&。&/p&
共 5024 字,读完需 6 分钟,速读需 2 分钟,本文首发于知乎专栏。写在前面,笔者在做面试官这 2 年多的时间内,面试了数百个前端工程师,惊讶的发现,超过 80% 的候选人对下面这道题的回答情况连及格都达不到。这究竟是怎样神奇的一道面试题?他考…
&figure&&img src=&https://pic4.zhimg.com/v2-9cf59d74496dcb1eb754a0_b.jpg& data-rawwidth=&533& data-rawheight=&300& class=&origin_image zh-lightbox-thumb& width=&533& data-original=&https://pic4.zhimg.com/v2-9cf59d74496dcb1eb754a0_r.jpg&&&/figure&&h2&什么是正则表达式&/h2&&p&正则表达式是对文本模式的描述,常用来检索、替换那些符合某个模式的文本。&/p&&h2&正则表达式的定义&/h2&&p&JavaScript中的正则表达式可以用两种方式来表示&/p&&ol&&li&使用RegExp()构造函数来创建RegExp对象;&/li&&li&使用直接量定义。&/li&&/ol&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&var pattern=new RegExp(&s&);
var pattern=/s/;
&/code&&/pre&&/div&&p&这两种方式都可以用以匹配任何包含“s”的字符串。&/p&&h2&正则表达式语法&/h2&&h3&常用字符&/h3&&figure&&img src=&https://pic2.zhimg.com/v2-dc2d418aaaff730a2639e0_b.jpg& data-rawwidth=&658& data-rawheight=&614& class=&origin_image zh-lightbox-thumb& width=&658& data-original=&https://pic2.zhimg.com/v2-dc2d418aaaff730a2639e0_r.jpg&&&/figure&&p&例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&/[a-z]/.test(&a&);//true
/[a-z]/.test(&A&);//false
/[^a-z]/.test(&A&);//true
/a./.test(&a&);//false
/a./.test(&aa&);//true
/\w/.test(&a&);//true
/\W/.test(&a&);//false
/\d/.test(1);//true
/\D/.test(1);//false
/\sJava\s/.test(& Java &);//true
/\sJava\s/.test(&Hello Java &);//true
&/code&&/pre&&/div&&p&注意:在正则表达式中,很多标点符号具有特殊含义,使用时需要进行转义:&/p&&p&^ $ . * + ? = ! : | \ / ( ) [ ] { }&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&'/test'.match(/\//);//[&/&, index: 0, input: &/test&]
'(test'.match(/(/);//Uncaught SyntaxError
'(test'.match(/\(/);//[&(&, index: 0, input: &(test&]
&/code&&/pre&&/div&&h3&重复&/h3&&p&我们可以在正则模式之后跟随用以指定字符重复的标记。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-cced84494_b.jpg& data-rawwidth=&493& data-rawheight=&389& class=&origin_image zh-lightbox-thumb& width=&493& data-original=&https://pic3.zhimg.com/v2-cced84494_r.jpg&&&/figure&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&/a{2,5}/.test(&a&);//false
/a{2,5}/.test(&aa&);//true
&/code&&/pre&&/div&&p&注意:“*”和“?”可能匹配0个字符,即允许什么都不匹配&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&/a?/.test(&&);//true
/a*/.test(&&);//true
/a*/.test(&b&);//true
&/code&&/pre&&/div&&p&正则表达式默认情况下匹配尽可能多的字符,即贪婪匹配。如果我们希望正则表达式进行非贪婪匹配,只需要在待匹配字符串后加“?”即可&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&aabab&.match(/a.*b/);//&aabab&.match(/a.*b/)
&aabab&.match(/a.*?b/);//[&aab&, index: 0, input: &aabab&]
&/code&&/pre&&/div&&h3&选择&/h3&&p&正则表达式中用“|”分割供选择的字符串。正则表达式的匹配是从左到右的,如果左侧的满足匹配,就忽略右侧的匹配。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&/a|e|g/.test(&abc&);true
/a|e|g/.test(&ef&);true
/a|e|g/.test(&ghi&);true
&/code&&/pre&&/div&&h3&分组&/h3&&p&之前的重复展示的是对单个字符的重复,如果我们想要对多个字符重复,需要使用分组。&/p&&p&把单独的项组合成分组,可以对分组进行其他操作。默认情况下,每组有一个组号,以左括号为标志。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&/java(script)?/.test(&java&);//true
/java(script)?/.test(&javascript&);//true
/(ab)b(c)\1/.test(&abbc&);//false
/(ab)b(c)\1/.test(&abbcab&);/true
&/code&&/pre&&/div&&h3&指定匹配位置&/h3&&p&正则表达式中的多个元素才能够匹配字符串中的一个字符。有一些正则表达式的匹配是字符之间的位置,而不是实际位置。\b匹配一个单词的边界,这些元素不匹配某个可见的字符,它们指定匹配发生的合法位置。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-b9cab820a96db01e642d9d7_b.jpg& data-rawwidth=&856& data-rawheight=&385& class=&origin_image zh-lightbox-thumb& width=&856& data-original=&https://pic1.zhimg.com/v2-b9cab820a96db01e642d9d7_r.jpg&&&/figure&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&test&.match(/^/);//[&&, index: 0, input: &test&]
&test&.match(/$/);//[&&, index: 4, input: &test&]
&test&.match(/\b/);//[&&, index: 0, input: &test&]
&test&.match(/\B/);//[&&, index: 1, input: &test&]
var str=&I'm studying while you are playing&;
str.match(/\b\w+(?=ing\b)/g);//[&study&, &play&]
&/code&&/pre&&/div&&h2&正则表达式的修饰符&/h2&&p&正则表达式中的修饰符是放在“/”外面的,JavaScript支持三个修饰符:&/p&&ol&&li&修饰符“i”,说明匹配模式不分大小写。&/li&&li&修饰符“g”,说明模式匹配是全局的,应该找出被检索字符串中所有的匹配。&/li&&li&修饰符“m”,用以多行模式中执行匹配&/li&&/ol&&h2&String&/h2&&ul&&li&search(),寻找字符串中匹配的起始位置,找不到返回-1;&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&aaa&.search(/a/);0
&aaa&.search(/ab/);-1
&/code&&/pre&&/div&&ul&&li&relpace(),替换字符串中匹配的字符&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&aaa&.replace(/a/,&b&);//baa
&aaa&.replace(/a/g,&b&);//bbb
&/code&&/pre&&/div&&ul&&li&match(),返回由匹配结果组成的数组&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&1a2b3c&.match(/\d/);//[&1&, index: 0, input: &1a2b3c&]
&1a2b3c&.match(/\d/g);//(3) [&1&, &2&, &3&]
&/code&&/pre&&/div&&ul&&li&split(),分割字符串&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&aaaa&.split(&&);//(4) [&a&, &a&, &a&, &a&]
&/code&&/pre&&/div&&h2&RegExp&/h2&&ul&&li&test(),判断是否匹配成功,是返回true,否返回false&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&/a/.test(&ab&);//true
&/code&&/pre&&/div&&ul&&li&exec(),返回当前匹配结果&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&var str = &a1a2a3&;
var reg = /a./;
console.log(reg.exec(str)[0]); // a1
console.log(reg.exec(str)[0]); // a1
var str = &a1a2a3&;
var reg = /a./g;
console.log(reg.exec(str)[0]); // a1
console.log(reg.exec(str)[0]); // a2
console.log(reg.exec(str)[0]); // a3
console.log(reg.exec(str)[0]); // null
&/code&&/pre&&/div&&h2&推荐&/h2&&a href=&https://link.zhihu.com/?target=http%3A//tool.oschina.net/regex/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&在线正则表达式测试&/a&&a href=&https://link.zhihu.com/?target=https%3A//regexper.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Regexper&/a&&br&&p&注:本文中的表格来源于《JavaScript权威指南》&/p&
什么是正则表达式正则表达式是对文本模式的描述,常用来检索、替换那些符合某个模式的文本。正则表达式的定义JavaScript中的正则表达式可以用两种方式来表示使用RegExp()构造函数来创建RegExp对象;使用直接量定义。var pattern=new RegExp("s");
var patte…
&figure&&img src=&https://pic1.zhimg.com/v2-3bc8c663e82eee8f9544_b.jpg& data-rawwidth=&600& data-rawheight=&338& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&https://pic1.zhimg.com/v2-3bc8c663e82eee8f9544_r.jpg&&&/figure&最近在逛各大网站,论坛,以及像SegmentFault等编程问答社区,发现Vue.js异常火爆,重复性的提问和内容也很多,楼主自己也趁着这个大前端的热潮,着手学习了一段时间的Vue.js,目前用它正在做自己的结业项目。&p&在做的过程中也对Vue.js的官方文档以及其各种特性有了许多认识。作为一个之前以PHP+模版引擎为主的开发,从一个从未接触过除HTML+CSS+JavaScript+JQuery以外的前端技术的人到现在可以独立使用Vue.js以及各种附属的UI库来开发项目,我总结了一些知识和经验想与大家分享。&/p&&p&下面我就以问答的形式来分享吧。这里假设你仅仅只掌握了HTML+CSS+JavaScript,如果你对JQuery这个前端库,以及各种后端模版语言比如说PHP,JSP还有所了解并且使用过的话那就太好了。&/p&&h2&1.Vue.js是什么?&/h2&&blockquote&&p&Vue.js(读音 /vju:/, 类似于 view) 是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用&a href=&http://link.zhihu.com/?target=http%3A//cn.vuejs.org/v2/guide/single-file-components.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&单文件组件&/a&和 &a href=&http://link.zhihu.com/?target=http%3A//github.com/vuejs/awesome-vue%23libraries--plugins& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Vue 生态系统支持的库&/a&开发的复杂单页应用。&/p&&p&Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。&/p&&p&如果你是有经验的前端开发者,想知道 Vue.js 与其它库/框架的区别,查看&a href=&http://link.zhihu.com/?target=http%3A//cn.vuejs.org/v2/guide/comparison.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&对比其它框架&/a&。&/p&&/blockquote&&p&这是官网的介绍,是不是觉得非常的抽象非常的官方?看完之后可能还是有很多人不是很懂这个框架到底是用来做什么的,什么是“渐进式框架”?什么是“自底向上增量开发”?什么是“视图层”?什么是“单文件组件”?什么是“复杂的单页应用?”第二段话里面“响应的数据绑定和组合的视图组件”这又是个啥?还有最后一段话,“Vue.js 与其它库/框架的区别”究竟是什么?&/p&&p&不要担心,如果你慢慢看完这里面的所有问答,一定会对前面那些可能你从未听说过的专业术语有一种恍然大悟的感觉。&/p&&h2&2.Vue.js到底是什么?&/h2&&p&想必现在能看到我这篇文章的人,都是用着APP或者网页版知乎在阅读把。Vue.js就是一个用于搭建类似于网页版知乎这种表单项繁多,且内容需要根据用户的操作进行修改的网页版应用。&/p&&h2&3.单页应用程序(SPA)&/h2&&p&顾名思义,单页应用一般指的就是一个页面就是应用,当然也可以是一个子应用,比如说知乎的一个页面就可以视为一个子应用。单页应用程序中一般交互处理非常多,而且页面中的内容需要根据用户的操作动态变化。&/p&&h2&4.你前面说的网页版知乎我也可以用JQuery写啊,为什么要用Vue.js呢?&/h2&&p&讲到JQuery,就不得不说到JavaScript的DOM操作了。如果你用JQuery来开发一个知乎,那么你就需要用JQuery中的各种DOM操作方法去操作HTML的DOM结构了。&/p&&p&现在我们把一个网页应用抽象一下,那么HTML中的DOM其实就是视图,一个网页就是通过DOM的组合与嵌套,形成了最基本的视图结构,再通过CSS的修饰,在基本的视图结构上“化妆”让他们看起来更加美观。最后涉及到交互部分,就需要用到JavaScript来接受用户的交互请求,并且通过事件机制来响应用户的交互操作,并且在事件的处理函数中进行各种数据的修改,比如说修改某个DOM中的innerHTML或者innerText部分。&/p&&p&我们把HTML中的DOM就可以与其他的部分独立开来划分出一个层次,这个层次就叫做&b&视图层&/b&。&/p&&br&&blockquote&Vue 的核心库只关注视图层&/blockquote&&p&我们为什么要把视图层抽取出来并且单独去关注它呢?&/p&&p&因为在像知乎这种页面元素非常多,结构很庞大的网页中,数据和视图如果全部混杂在一起,像传统开发一样全部混合在HTML中,那么要对它们进行处理会十分的费劲,并且如果其中有几个结构之间存在藕断丝连的关系,那么会导致代码上出现更大的问题,这什么问题呢?&/p&&p&你是否还记得你当初写JQuery的时候,有写过$('#xxx').parent().parent().parent()这种代码呢?当你第一次写的时候,你觉得页面元素不多,不就是找这个元素的爸爸的爸爸的爸爸吗,我大不了在注释里面写清楚这个元素的爸爸的爸爸的爸爸不就好了。但是万一过几天之后你的项目组长或者你的产品经理突然对你做的网页提出修改要求,这个修改要求将会影响页面的结构,也就是DOM的关联与嵌套层次要发生改变,那么$('#xxx').parent().parent().parent()可能就会变成$('#xxx').parent().parent().parent().parent().parent()了。&/p&&p&这还不算什么,等以后产品迭代越来越快,修改越来越多,而且页面中类似的关联和嵌套DOM元素不止一个,那么修改起来将非常费劲。而且JQuery选择器查找页面元素以及DOM操作本身也是有性能损失的,可能到时候打开这个页面,会变得越来越卡,而你却无从下手。&/p&&p&当你在编写项目的时候遇到了这种问题,你一定会抱怨,为什么世上会有HTML这种像盗梦空间一样的需要无数div嵌套才能做出页面的语言,为什么当初学JQuery看中的是它简洁的DOM操作,现在却一点也不觉得它有多简洁,难道我学的是假的JQuery?为什么写个代码这么难,你想砸电脑,你想一键盘拍在产品狗的脑袋上,责怪他天天改需求才让你原本花清香茶清味的代码变得如此又臭又长。&/p&&p&这个时候如果你学过Vue.js,那么这些抱怨将不复存在。&/p&&h2&5.Vue.js为什么能让基于网页的前端应用程序开发起来这么方便?&/h2&&p&因为Vue.js有声明式,响应式的数据绑定,与组件化的开发,并且还使用了Virtual DOM这个看名字就觉得高大上的技术。&/p&&p&可是这些名词都是啥?&/p&&h2&6.响应式的数据绑定&/h2&&p&这里的响应式不是@media 媒体查询中的响应式布局,而是指vue.js会自动对页面中某些数据的变化做出响应。至于是如何响应的,大家可以先把下面这段代码随便粘贴到一个扩展名为html的文件然后用浏览器打开,随便在文本框里面输入一些文字,观察一下页面变化。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&!DOCTYPE html&
&html lang=&en&&
&meta charset=&UTF-8&&
&title&vue.js测试 - 代码之美专栏&/title&
&!-- author:昌维 代码之美 https://zhuanlan.zhihu.com/codes --&
&script src=&https://unpkg.com/vue/dist/vue.js&&&/script&
&div id=&app&&
&input type=&text& name=&& value=&& placeholder=&在这里输入文字,下面会跟着变化& v-model=&message&&
&p&{{ message }}&/p&
&script type=&text/javascript&&
var app = new Vue({
el: '#app',
message: 'Hello Vue!'
&/code&&/pre&&/div&&p&是不是会发现一个很神奇的现象,文本框里面输入的文字和后面的p标签中的内容一起变化?&/p&&p&换句话说,p标签里面通过{{ message }}这个写法与input标签中的value绑定在了一起,其中变化,另外一个和它绑定的数据就跟着变化。&/p&&p&结合标题来说,就是vue.js会自动响应数据的变化情况,并且根据用户在代码中预先写好的绑定关系,对所有绑定在一起的数据和视图内容都进行修改。而这种绑定关系,在图上是以input 标签的v-model属性来声明的,因此你在别的地方可能也会看到有人粗略的称vue.js为声明式渲染的模版引擎。&/p&&h2&7.组件化开发&/h2&&p&还记得在传统前端开发的时候,我们都是每个人做一个页面,然后最后套入各种后端模版引擎,比如说PHP的Smarty或者Java的JSP等等。&/p&&p&但是现在我们做单页应用,页面交互和结构十分复杂,一个页面上就有许许多多的模块需要编写,而且往往一个模块的代码量和工作量就非常庞大,如果还按照原先的方法来开发,那么会累死人。而且遇到以后的产品需求变更,修改起来也非常麻烦,生怕动了其中一个div之后,其他div跟着雪崩,整个页面全部乱套,或者由于JavaScript的事件冒泡机制,导致修改一些内层的DOM事件处理函数之后,出现各种莫名其妙的诡异BUG。&/p&&p&在面向对象编程中,我们可以使用面向对象的思想将各种模块打包成类或者把一个大的业务模块拆分成更多更小的几个类。在面向过程编程中,我们也可以把一些大功能拆分成许多函数,然后分配给不同的人来开发。&/p&&p&在前端应用,我们是否也可以像编程一样把模块封装呢?这就引入了组件化开发的思想。&/p&&p&Vue.js通过组件,把一个单页应用中的各种模块拆分到一个一个单独的组件(component)中,我们只要先在父级应用中写好各种组件标签(占坑),并且在组件标签中写好要传入组件的参数(就像给函数传入参数一样,这个参数叫做组件的属性),然后再分别写好各种组件的实现(填坑),然后整个应用就算做完了。&/p&&h2&8.Virtual DOM&/h2&&p&现在的网速越来越快了,很多人家里都是几十甚至上百M的光纤,手机也是4G起步了,按道理一个网页才几百K,而且浏览器本身还会缓存很多资源文件,那么几十M的光纤为什么打开一个之前已经打开过,已经有缓存的页面还是感觉很慢呢?这就是因为浏览器本身处理DOM也是有性能瓶颈的,尤其是在传统开发中,用JQuery或者原生的JavaScript DOM操作函数对DOM进行频繁操作的时候,浏览器要不停的渲染新的DOM树,导致页面看起来非常卡顿。&/p&&p&而Virtual DOM则是虚拟DOM的英文,简单来说,他就是一种可以预先通过JavaScript进行各种计算,把最终的DOM操作计算出来并优化,由于这个DOM操作属于预处理操作,并没有真实的操作DOM,所以叫做虚拟DOM。最后在计算完毕才真正将DOM操作提交,将DOM操作变化反映到DOM树上。&/p&&p&对于vue.js的Virtual DOM,目前业界有着褒贬不一的评价。有人认为Vue.js作为一个轻量级框架,引入Virtual DOM会加大Vue.js本身的代码尺寸,也会消耗更多CPU(手机上会更耗电)(注意:消耗更多的CPU并不意味着会更卡,因为JavaScript计算是后台计算,他的计算量还不至于让DOM操作变得卡顿),并且在操作单个DOM元素的时候,反而多了一道计算工序,会更慢。但也有人认为基本上会用Vue.js开发的都是页面中内容很多的元素,肯定操作的DOM量级普遍较大,平均一下还是比较划算的。&/p&&h2&9.我到底该怎么用Vue.js做单页应用开发?&/h2&&p&说了这么多,我还是不知道怎么用它做出一个像知乎那样的页面啊,到底怎么学它呢?&/p&&p&前面我们看了一个响应式的数据绑定案例,那只是一个DEMO,而且也看不出有什么实际意义,离真正的单页应用程序还差得远,到底怎么用它开发真实的项目呢?&/p&&p&我的建议是,先把&a href=&http://link.zhihu.com/?target=http%3A//cn.vuejs.org/v2/guide/index.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&介绍 - vue.js&/a&官方文档的基础部分硬着头皮看一遍。除了组件这个小节涉及到了很多晦涩难懂的名词以外,前面几章完全就是把Vue.js当作一个模版引擎来用。&/p&&p&然后开始学习ECMAScript6,Webpack,NPM以及Vue-Cli的基本用法,最好对Node.js也要有所了解。&/p&&p&最后组件部分先大致看一遍,了解组件里面都有哪些概念之后,开始看网上各种实战视频以及文章还有别人开源的源代码。&/p&&h2&10.在前面你提到过好几次ECMAScript,这是啥?&/h2&&p&ECMAScript听名字好像和JavaScript很像,难不成他们有什么千丝万缕的联系?&br&&/p&&p&没错你猜对了,他们之间还真有着很深的联系。&/p&&p&引用阮一峰老师的话:(&a href=&http://link.zhihu.com/?target=http%3A//es6.ruanyifeng.com/%23docs/intro& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ECMAScript 6入门&/a&)&/p&&blockquote&&p&要讲清楚这个问题,需要回顾历史。1996年11月,JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给国际标准化组织ECMA,希望这种语言能够成为国际标准。次年,ECMA 发布262号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript,这个版本就是1.0版。&/p&&p&该标准从一开始就是针对 JavaScript 语言制定的,但是之所以不叫 JavaScript,有两个原因。一是商标,Java 是 Sun 公司的商标,根据授权协议,只有 Netscape 公司可以合法地使用 JavaScript 这个名字,且 JavaScript 本身也已经被 Netscape 公司注册为商标。二是想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保证这门语言的开放性和中立性。&/p&&p&因此,ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 Jscript 和 ActionScript)。日常场合,这两个词是可以互换的。&/p&&/blockquote&&p&而ECMAScript6就是新一代的JavaScript语言。&/p&&p&这里也强烈推荐大家学习ECMAScript6的时候参考这本书&a href=&http://link.zhihu.com/?target=http%3A//es6.ruanyifeng.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ECMAScript 6入门&/a&&/p&&h2&11.我在学习Vue.js的时候老是听到Webpack,这是啥?&/h2&&p&Webpack是一个前端打包和构建工具。如果你之前一直是手写HTML,CSS,JavaScript,并且通过link标签将CSS引入你的HTML文件,以及通过Script标签的src属性引入外部的JS脚本,那么你肯定会对这个工具感到陌生。不要紧,我们先来了解一下为什么要用Webpack,然后带着原因去学习就好了。&/p&&h2&12.为什么要用Webpack&/h2&&p&前面说了,做一个单页应用程序本身就相当复杂,而且在做的时候肯定会使用到很多素材和别的第三方库,我们该如何去管理这些东西呢?&/p&&p&还有前面讲到了Webpack是一个前端打包工具,前端代码为什么要打包呢?因为单页应用程序中用到很多素材,如果每一个素材都通过在HTML中以src属性或者link来引入,那么请求一个页面的时候,可能浏览器就要发起十多次请求,往往请求的这些资源都是一些脚本代码或者很小的图片,这些资源本身才几k,下载连1秒都不需要,但是由于HTTP是应用层协议,它的下层是TCP这个运输层协议,TCP的握手和挥手过程消耗的时间可能比下载资源本身还要长,所以需要把这些小文件全部打包成一个文件,这样只要一次TCP握手和挥手的过程,就把多个资源给下载下来了,并且多个资源由于都是共享一个HTTP请求,所以head等部分也是共享的,相当于形成了规模效应,让网页展现更快,用户体验更好。&/p&&br&&p&前面说到Webpack还有构建的功能,这就不得不提到了ECMAScript6这个新版本的JavaScript,但是现在国内外还有很多人用着老版本的浏览器,这些浏览器并不支持ECMAScript6,那么我们的前端项目如何在这种浏览器上运行呢?这就需要Webpack的Loader自动载入一个转换器来将我们写的ECMAScript6转换成浏览器能支持的老版本JavaScript语言,这个转换器的名字叫做babel,如果你以后听到或者看到了这个单词,应该要知道它就是一个ECMAScript6 to 老版本JavaScript的转换器了。这也是Webpack的构建功能。当然对前端有更深入的同学还会知道Sass,Less,stylus之类的CSS预处理器,我们也可以通过在Loader中编写特定的规则来实现自动将这些CSS预处理语言转换成普通浏览器能识别的CSS代码。&/p&&p&开头的介绍提到了vue.js可以使用单文件组件开发项目,其实也是通过Webpack将单文件组件中的模版,样式以及JS转换到主页面中&/p&&p&当然Webpack不止这点功能,它还可以通过安装各种插件来扩展,比如说热加载技术,就是解放键盘的F5键。让我们修改代码,并且按Ctrl+S保存之后,浏览器页面自动刷新变化,不需要我们去手动刷新,还有一些插件可以自动添加注释,自动给CSS代码加上一些浏览器内核对CSS3兼容前缀,就像webkit-xxx之类的一样。&/p&&h2&13.NPM和Node.js又是什么?它们是什么关系?&/h2&&p&首先讲讲Node.js。我们知道通常情况下,JavaScript的运行环境都是浏览器,因此JavaScript的能力也就局限于浏览器能赋予它的权限了。比如说读写本地系统文件这种操作,一般情况下运行在浏览器中的JavaScript代码是没有这个操作权限的。如果我们想用JavaScript写出一些能够运行在操作系统上的,能够具有像PHP,JAVA之类的编程语言具有的功能的程序该怎么办呢?Node.js就解决了这个问题。Node.js是一个服务端的JavaScript运行环境,通过Node.js可以实现用JavaScript写独立程序。像我们之前提到的Webpack就是Node.js写的,所以作为一个前端开发,即使你不用Node.js写独立程序,也得配一个Node.js运行环境,毕竟很多前端工具都是使用它写的。&/p&&p&NPM是一个node.js的包管理器。我们在传统开发的时候,JQuery.js大多都是百度搜索,然后去官网下载,或者直接引入CDN资源,这种方法太过于麻烦。如果以后遇到其他的包,这个包的代码本身可能还调用了其他的包(也称这个包和其他的那几个包存在依赖关系),那么我们要在自己的项目中引入一个包将变得十分困难。现在我们有了NPM这个包管理器,直接可以通过&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&npm install xxx包名称
&/code&&/pre&&/div&&p&的方式引入它,比如说&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&npm install vue
&/code&&/pre&&/div&&p&就自动在当前项目文件夹下导入了这个包,并且npm自动下载好了vue这个包依赖的其他包。&/p&&p&至于有的人在按照网上的npm教程配置的时候踩坑了,发现下载速度很慢或者完全下载不了,那是因为我国有着众所周知的原因,网上也有各种解决方法可以解决这个问题,大家多善用搜索引擎。&/p&&p&前面提到了Webpack可以安装各种插件来扩展功能,其实也是通过这种方式扩展。&/p&&p&如果你学过PHP的话,NPM就和PHP里面的Composer差不多。也和CentOS下的yum和Ubuntu下的apt-get差不多。&/p&&h2&14.Vue-CLi又是啥?&/h2&&p&它是一个vue.js的脚手架工具。说白了就是一个自动帮你生成好项目目录,配置好Webpack,以及各种依赖包的工具,它可以通过&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&npm install vue-cli -g
&/code&&/pre&&/div&&p&的方式安装,后面的-g表示全局安装的意思,意味着你可以打开命令行之后直接通过vue命令调用它。&/p&&h2&15.我该不该学Vue.js?&/h2&&p&现在Vue.js无论是发展势头还是作者支持还是很好的,而且它本身中文资料就比较多,教程也很多,现在随随便便打开几个和前端开发有关的知乎专栏,基本上都能见到相关文章,社区也很活跃。&/p&&p&至于你该不该学,取决于你自己,如果你当前只是做做以内容展示为主的项目,或者就是成天用各种CMS建站仿站,并且以后都不打算更换更好的工作,那么可以暂时不用学。如果你开发的项目交互非常多,而且前后端开发都对前后端分离有很清楚的认识,那么可以大胆的学习,并且在实际项目中运用。&/p&&h2&16.Vue.js怎么火起来的?&/h2&&p&关于这个问题,网上说法很多,我自己认为主要还是前些年大前端变革太快,而最近一年开始Vue.js+Webpack这个组合开始逐渐稳定下来了,而且已经有了很多中文资料。&/p&&p&对比它的竞争对手AngularJS,新旧版本项目无法平滑升级,变革太大让用户感觉不安稳。&/p&&p&而React本身主流推荐用的是JSX,需要额外学习一门语法(什么?学Vue.js还要学ECMAScript6?现在ECMAScript6是趋势,并不是因为Vue.js才要学的),并且React本身用的是render写法编写模版代码,这让很多用习惯了Smarty等后端模版引擎得人来使用感觉很不适应,现在看来React本身在中国一些论坛社区的火爆程度还是没有Vue.js高。&/p&&p&当然也并不是说除了Vue.js以外其他框架都很差。像知乎新版也是用React开发的,他还是有各自优秀的地方大家可以深入学习之后做出自己的判断。&/p&&h2&17.我在很多地方还看到Vuex和Vue-route,它们又是什么?&/h2&&p&Vuex是vue的一个状态管理器。用于集中管理一个单页应用程序中的各种状态。&/p&&p&Vue-route是vue的一个前端路由器,这个路由器不是我们上网用的路由器,而是一个管理请求入口和页面映射关系的东西。它可以实现对页面局部进行无刷新的替换,让用户感觉就像切换到了网页一样。&/p&&p&要讲清楚这两个东西,又得花费大量篇幅,所以这里只是简单提一下,先学好vue.js本身才是最重要的。&/p&&h2&18.我还在一些地方看到过Vue-resource和Axios,它们又是什么?&/h2&&p&我们在传统的前后端不分离的开发中,后端直接把数据通过模版引擎拼接进了返回的HTML中。而现在做单页应用程序属于前后端分离开发,那么这个单页应用程序中的数据就得通过ajax的方式获取,也要通过ajax的方式提交到后端。&/p&&p&在传统开发中我们都是通过xmlhttprequest手动操作,或者通过JQuery的ajax方法来进行数据提交获取。&/p&&p&vue.js本身没有封装ajax操作库,所以我们要通过Vue-resource和Axios来进行ajax操作,而因为种种原因,现在vue.js2.0已经将axios作为官方推荐的ajax库了。&/p&&h2&19.我该学Vue.js2.0还是1.0呢?&/h2&&p&现在很多框架和语言都是学新不学旧(Python慢慢也变得如此),因此如果不是为了维护老旧项目,肯定推荐学Vue.js2.0。而且学会了Vue.js2.0,再去学习Vue.js1.0也不是什么难事。&/p&&h2&20.写Vue.js用什么开发工具和电脑呢?&/h2&&p&前端开发基本上不需要太高端的电脑都能胜任,现在这个时代是台电脑,装个编辑器都可以做前端开发的。&/p&&p&Vue.js的组件文件本质上还是普通的代码文件,所以各种编辑器配合一些语法检查插件就足够了。我自己用的是sublime text 3,安装一些插件之后可以实现.vue单文件组件高亮代码以及各种自动完成。Webstorm中也有类似插件,大家可以在网上各种教学文章的指导下配置好环境。&/p&&h2&结语:&/h2&&p&可能包括我在内的很多人在看到Vue.js那神奇的双向绑定优雅写法都会有一种非常惊艳,而看到中文文档发布之后有种想立马学习的冲动。可惜大前端终究是大前端,如果一个对于前端各个方面没有深入认识就想着能一步登天,肯定对不起大前端的“大”字。原本看着只想学一个Vue.js,没想到顺带把ECMAScript6,Webpack配置,ESLint配置,bable配置,npm使用,node.js语法,以后vue全家桶中的vuex,vue-route等等等等都学了一遍。前段时间网上也流传出了一个职位叫做Webpack配置工程师,从这里也可以看出弄懂前端这个大杂烩确实不是那么容易。大家一起加油,有什么问题也可以在评论区回复,我会抽空补充在文章内容中。谢谢各位的支持!~&/p&&br&&p&本文章由 &a data-hash=&5fe93d9ed5cb4c& href=&http://www.zhihu.com/people/5fe93d9ed5cb4c& class=&member_mention& data-hovercard=&p$b$5fe93d9ed5cb4c& data-editable=&true& data-title=&@昌维&&@昌维&/a& 原创,在知乎专栏-代码之美 &a href=&https://www.zhihu.com/codes& class=&internal&&https://zhuanlan.zhihu.com/codes&/a& 首发,转载请注明出处。大家喜欢和支持我的文章可以点开我的头像以及专栏名称进行关注,或是点击下方的打赏按钮进行支持,谢谢。^_^&/p&
最近在逛各大网站,论坛,以及像SegmentFault等编程问答社区,发现Vue.js异常火爆,重复性的提问和内容也很多,楼主自己也趁着这个大前端的热潮,着手学习了一段时间的Vue.js,目前用它正在做自己的结业项目。在做的过程中也对Vue.js的官方文档以及其各种特…
&figure&&img src=&https://pic2.zhimg.com/v2-a33ff55a21ab514d3bee1a7_b.jpg& data-rawwidth=&750& data-rawheight=&340& class=&origin_image zh-lightbox-thumb& width=&750& data-original=&https://pic2.zhimg.com/v2-a33ff55a21ab514d3bee1a7_r.jpg&&&/figure&&blockquote&&p&原文链接:&a href=&https://link.zhihu.com/?target=http%3A//www.luckyjing.com/posts/front-end/learn-front-end.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何在有限时间内尽可能高效率地学习前端? · LuckyJing Blog&/a&&/p&&p&作者:luckyjing&/p&&/blockquote&&br&&blockquote&&p&本文写于日。&/p&&/blockquote&&p&当你看到标题,便有一种本能点进来瞅瞅的时候,你可能是初涉前端,想在找工作前夕尽快地丰富自己的技能;也可能已经是前端经验非常丰富的人,来瞧瞧这个小子会写一些什么奇怪的文字;当然,你也可能是涉及任何一个领域,和我一样想在毕业后写代码挣钱养家的程序员,无论角色怎样,如果你身边有在前端路上稍微迷茫的同学的话,或许我的一点心得能够帮上一些忙,下面是仔仔的一些感悟,水平有限,所以还请多多包涵。&br&&/p&&blockquote&&p&我今年大三,大一下学期开始接触前端,在一波波春季实习生招聘的浪花里,收获了阿里,腾讯,网易三家的前端实习生offer,结果也出乎我的意料,但是真心觉得js是世界上最好的语言。(玩笑话)&/p&&/blockquote&&p&撇开具体细节来讲,前端相对于后端,直接摆在了用户面前,如果说后端面向的主要是业务逻辑,数据}

我要回帖

更多关于 js正则表达式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信