根据APP的推荐文章和杂志阅读排行榜来看,APP的用户应该还是偏年轻,所以我认为APP的目标用户应该是24岁以下的学生群体或一些自由作家等,主要偏高中生、初中生等。他们有一些课外时间,比较有兴趣去阅读这些简短的文章。在繁重的学习作业之外,这可能是他们唯一的释放学习压力的课外读物。
因为没有做问卷调查和用户访谈,没法精准的做一些用户画像分析。我用了一些互联网用户分析工具。下面是易观万象的一些统计截图。
根据分析工具,我们发现:这部分目标用户大部分为女性,消费水平偏中下水平,使用的手机主要还是中低档手机,人群分布主要在长三角、珠三角等沿海发达城市。
根据每个人的所处环境和生活习惯不同,读文章和看书籍的品味也是不一样的。一般来说,读者,意林等杂志类的书刊,是有一些共同性的,也就有类似的用户需求:
(1)从内容上得到一些启发。读者一类的书刊,文章都是短篇的,具有较为完整的寓意和结构,一般结尾都是有情感的抒发和道理的论述。我们读一读,有的时候会有一些思维上的启发,这是比较重要的。
(2)打发时间。虽然这样说起来有一些唐突,但实际上,因为都是短篇的小文章,更适合于短时间内品读。比如等车的时候,外出乘车的时候,阶段性的时间内可以打发一下时间,这类书刊主要针对的就是这些情况。
(3)写作素材,这些杂志里的文章都还选取的不错,对于一些中学生来说,可以得到一些不错的写作素材。
(4)文化的传播,这类书刊一般价格较低,更能被大众接受。有些文章是可以从其他书刊上转载来的,也相对精华。由于传播范围较广,也能使一些精华的文章被更多人品读,这也是在一定程度上,对于优秀文化的传播,起到了推动作用。
上面介绍的是纸质书就可以解决的用户需求,为什么要用APP去看这些杂志书籍呢?
(1)在APP里看杂志方便,只要打开手机就能看,不受时间、空间的限制。可以充分利用碎片时间,无论是乘车、课间、饭后、还是睡前都可以看。
(2)在APP里看杂志省钱,一本杂志大概是七八块钱左右,一个月按两期算,订两三种,一个月大概要几十块钱左右。而在APP里可能也就十几块钱。
(3)在APP里内容更加丰富,我可以看同类型的所有杂志,我也可以快速找到我想看的文章。
(4)在APP里更加方便的收藏好的文章、好的句子,更加方便的去做一些笔记。
###3、用户需求的市场量有多大?
行业概述:2017年中国移动阅读市场规模稳步上升达132.2亿,同比增长32.1%,增长率相比去年有所降低。2017年中国移动阅读行业用户规模达到3.4亿,同比增长13.2%,增长率较之去年有明显下降。
发展现状:移动阅读行业正版化得到极大的发展,各大内容平台的优势逐渐凸显,整个市场竞争格局趋于稳定。其中阅文集团、掌阅科技、咪咕数媒、阿里文学以超过7%的APP月度覆盖人数占比稳坐第一梯队。
发展趋势:移动阅读APP不断正版化,用户付费习惯逐渐养成且持续提升。影视二次元游戏全IP化,共享版权模式出现。
轻阅读领域类似产品情况如下:
这些APP2018年2月月活量分别是一个148万、知乎日报158万、每天读点故事63万、诗歌本42万。在轻阅读领域已经算非常不错了,毕竟这个需求不是像即时通讯那么大众。
根据百度和其官网等一些渠道可得知:读者月发行量大约在800万左右,意林月发行量大约在200万左右。如果能将这些纸质上的用户完全转化为产品用户,那其实也是一个比较可观的用户量。
意林2010年6月,数字出版部成立。
读者2011年首款苹果App上线,当年客户端下载量即突破300万。
随着移动互联网的崛起,传统杂志社逐渐面临转型,杂志类移动数字阅读变得越来越重要。
(1)移动数字阅读 VS 传统纸质阅读
现如今,对于读者、意林等杂志用户数量传统纸质阅读应该还是占据主导,但随着出版社和用户观念的逐渐转变,相信移动数字阅读会逐渐展现优势。
传统纸质阅读代表:线下书店。
(2)杂志数字出版物 VS 网络文学出版物
杂志数字出版物和网络文学出版物,在用户层次上将会有大部分重合,所以它们可能存在竞争关系。但在需求层次上,它们将是两个不同的需求,杂志数字出版物面对的需求可能更多的是学习、心灵启发等;网络文学出版物更多是快餐式文化,解决的是用户精神娱乐层面的需求。
网络文学出版物代表:咪咕、阅文集团、掌阅等。
(3)杂志数字出版物 VS 其他数字出版物
杂志数字出版物与其他数字出版物,在用户层次上有部分重合,杂志数字出版物偏向于24岁以下的学生群体,他们学习压力较重,没有足够多的时间去阅读内容较长的文学作品,他们更多的精力是会花在课内学习中;而其他数字出版物偏向于毕业之后的上班白领阶级,他们有较好的收入,有积极提升自己的意向。
其他数字出版物代表:一些职业提升书籍、世界名著等。
下面的产品分析没有说明的部分,都以小读APP为例。
定位:成功人士的随身轻阅读应用
slogan:小读怡情
主要亮点:
1、每日小文推送,小读怡神旷心
告别碎片阅读,告别长篇大论,小读,带给你不一样的阅读体验
2、千册杂志更新,小读增雅添趣
海量杂志,随时阅读,“小读”会员,畅读百余种国内主流杂志,轻松掌握各类讯息。
杂志内容完整,排版精良,阅读体验媲美纸版杂志
高质量的文章与图片,负责任的内容。
您将无需再奔波于路边报刊亭,或翻阅厚重的纸刊,轻松下载既可享受时尚的阅读新体。
3、查找便捷
可以搜索你想看的杂志和内容
上面都是小读APP里介绍的,经过几天的体验和一些用户分析,说说我的感受。
产品是内容定位是杂志类内容阅读,用户群体大部分是从纸质阅读迁移过来的。所以产品的用户群体应该只是纸质用户的一个子集。从产品的用户数据来看这部分用户大部分是24岁以下的年轻用户。APP里排名前三的杂志分别是:读者、故事会、意林。这些杂志的用户群体应该都是偏年轻的,而不是偏商业的。而且推荐文章也基本上是偏娱乐、文艺的,而不是偏商业的。所以用户定位为成功人士我感觉是矛盾的。
“告别碎片阅读,告别长篇大论”,并没有突出重点。我认为应该突出“精选阅读,推荐优质文章,告别信息繁多,无效阅读”。
产品分为5大板块:小文、小书、全站畅读、书架、我的。
小文:每日推送文章,用户可以签到,可以阅读自己喜欢的文章,也可以搜索自己喜欢的文章,但是查找功能有点弱,只能按标题名或杂志书名查找,其实可以给文章分类加标签等,用户搜索的时候可以查找的范围包括标题、书名、标签等,这样查找出的内容可能更符合用户思维。
进入文章页面,可以阅读文章,可以调整自己的阅读风格,阅读完文章,系统将推荐两篇相关文章,当然也可以为该文章点赞,可以评论文章等。
小书:这个版块,用户一进入就可以看到书籍分类菜单,左上角也可以查看分类信息,用户可以直接了当的进入自己喜欢的类目。如果用户比较盲目,不知道看哪些书,那么系统将会给一些推荐,如排行榜、免费专区、编辑推荐、新书上架等。如果用户一进入页面目标就很明确,那么用户也可以用右上角的搜索书籍功能。
选择好自己想要阅读的书名后,用户可以查看该书的所有期数,可以选择查看哪期,然后进入当前期杂志页面,在该页面你可以查看到这本杂志的一些介绍,阅读、下载、关注该杂志。系统也将会为用户推荐看过此杂志的人还看过哪些杂志。这个阅读书籍的路径有点长,对于用户来说,是比较烦的一个过程,每次阅读一本杂志都要经过这么长的一个路径,应该尽量缩短阅读路径。在小书界面,查找或选中那本杂志之后,直接进入该杂志最新一期的杂志介绍页面,至于往期杂志的入口也可以放在这个地方。对于用户来说,尤其是经常使用的用户,他往往想看的就是最新一期的杂志。在产品设计理念里,用户路径最好控制在三层以内。
全站畅读:这个版块做的其实比较简单,就是一个付费订阅页面,而且放在一个最显著的位置。我感觉是有点不妥的。整个APP到处都放着VIP订阅入口,感觉还是以传统的思维在做互联网产品,这似乎时刻在告诉用户:“你再不付费,我就不给你看了”。其实放在这也不是不可以,可以参考喜马拉雅APP的VIP页面,作为一个产品,你得要有足够的吸引力,才能促使用户付费,不是说我一直在你耳边念叨着“赶紧付费,赶紧付费,赶紧付费 ….. ”,用户就会付费订阅,这样只会引起用户的反感。
书架:在书架版块你可以查看到你最近阅读的是哪本书,你的书架里有哪些书。你可以整理你的书架,把一些不看的书籍删掉。如果你的书籍很多,你可以用右上角的搜索去搜索你想看的书,当然这里的书是指你书架里的书。有个不好的体验,这里书籍的排列顺序是按照你加入的时间,之后的顺序就不能再变化了,因为并不能对书籍排序。整理书籍和查找书籍,我猜想可能正是为了解决这个问题吧。
点击最近阅读进入的是该书的目录页面,并没有回到你上次阅读的起点,也没有书签功能。点击下面的书籍进入的是该书籍集合页面,选择哪期后才能进入该书的目录。这个阅读路径还是比较长,虽然文章很短,但有时也不知道自己读到了哪里,没有书签真的是会比较麻烦,至少也要告诉用户哪些是已经阅读过的。
我的:在“我的”版块,用户可以看到自己的一些个人账户信息、关注收藏信息,还有一些设置项。这个版块有个不好的地方是,直接把用户的手机号作为用户名了,虽然这个地方可以修改,但有些不注重个人信息隐私的人,将很容易泄露自己的电话号码。
产品的整体UI看来,感觉还是比较陈旧。
“小文”这个模块有点像资讯类APP,感觉内容过多,页面过于凌乱,在这个信息爆炸的时代,你越能击中用户的需求点,就越能获取用户的喜爱。精准的推荐和简洁的界面是产品比较欠缺的。
里面文章的阅读风格还是偏资讯类的风格,并没有突出自己的特点。很多用户可能都是从纸质阅读迁移过来的,他们更希望能体验到纸质阅读那种畅快。作为一页到底的去展示一篇文章,而不是书籍翻页去展示,我感觉是比较好的。评论模块,我感觉是体验比较差的,虽然需要评论,但可以隐藏一点,我有自己的感想,我有自己的认知,我不想受别人影响,可能也不想和别人分享。毕竟杂志类文章,不是时事评论,不是新闻资讯,里面的文章基本上是观点类文章。
书籍阅读界面不太统一。有的像资讯文章界面,有的是PDF扫描版。我觉得需要统一,尽可能保持一致的体验。
支付宝支付接口经常支付失败。
从用户评价反馈来看,还是有挺多待优化的地方,丰富的内容是APP最大的优势。
优点:内容丰富、更新比较快。
缺点:交互体验差、不太稳定,时常黑屏闪退。
毕竟是一款比较小众的APP,网上可以查询到数据太少了,只做了一个大概的下载量和月活数的推测。其他的用户人群分析、访问时长与时段、访问终端等数据还是比较难推测。
我从锋阅网APP中选取了用户量最大的三个APP,作为此次运营分析的重点。以下数据来源根据艾瑞数据、易观千帆、七麦数据、APP Annie等数据源推测而来,数据为Android和iOS的总和。
读者 | 意林 | 小读 | |
---|---|---|---|
下载量 | 约162万 | 约67万 | 约25万 |
月活 | 约3万 | 小于1万 | 小于1万 |
简单介绍一下我的数据推算过程
下载量:下面是七麦数据关于读者杂志APP的下载量统计,其中华为的下载量占比约为25.69%,而我的华为手机下载量显示34万,则安卓的下载量大约为132.3万,iOS的下载量为29.8万,所以总下载量大约为162万。
月活:直接查看的艾瑞指数,读者2018年8月大约3万月独立设备数。
无论是读书,还是看杂志都是一种提升自我、丰富生活、充满正能量的事情。但并不是每个人都能坚持去阅读,兴趣使然的用户可能仅是一小部分,怎样使更多的人去养成这种习惯,是产品经理和运营人员都得考虑的一个问题。
只做简单的介绍,抛个砖,不做深入探讨,毕竟没有深入了解过这个行业,不敢妄下结论。但无论什么行业什么产品,完美的解决用户需求、更好的实现企业发展、良好的用户体验与粘性都是产品规划必须要考虑的。曾经有个做产品的师长对我说,产品无小事。的确,做好一个产品你得关注每一个细节,每个节点。
(1)更加便捷的获取信息
(2)更纯粹的还原纸质阅读
(3)智能化推荐文章
(4)优化产品交互体验
(1)提高书籍制作的质量
(2)内容多样化,后面可以增加纸媒、非杂志类出版物等
(3)UGC内容社区或者PGC内容社区
(1)内容付费
(2)优质内容打赏
(3)衍生IP产品
优势(Strengths):丰富的杂志内容,这将吸引一大批相应杂志的喜爱者,这一优势将明显降低用户获取成本和提高用户付费转化率。
劣势(Weaknesses):相对于纸质杂志阅读,在体验上还有待提升。对于杂志,更多人可能还是更喜欢纸质阅读。降低产品的转移成本,提高产品使用体验。
机会(Opportunities):综合性的杂志阅读APP基本上是一片空白,虽然有一些杂志出版社也推出了属于自己的APP,但用户群体还是仅限于喜爱该杂志的用户。
威胁(Threats):品牌识别度过小,用户缺乏对APP的信任感。受杂志出版社的版权限制。
2017年,在我身上其实发生了很多事。也许没有找到合适且懂你的人,很多事都宁愿埋在自己的心里,也不愿和别人分享。
2017年前,我一直以为我会是一个很好的前端,会在这条道路上越走越远,成为一个别人认为很厉害的人,这应该是我当初的梦想。可是人生的轨迹似乎总是难以预料。
2017年3月,我眼睛出现了问题,视网膜脱落,很严重。我请了三个月的病假,在家养病。这段时间,我不能看电脑玩手机,一切需要眼睛做的事情,我都做不了。我除了吃饭,就是躺在床上听有声书、广播新闻等。有一段时间,我真的很沮丧,迷茫。可能已经不能用迷茫来描述了,应该是绝望。
这段时间让我想了很多,我考虑了最坏的情况,也想了我的未来。我在想,我未来会不会在哪个盲人按摩店,帮客人按摩,或是在街头卖艺乞讨 . . .
我其实挺感谢老天给我这次经历的,虽然这远远不是我最悲惨的一段时光。养病期间,我一天可能十八小时都在听喜马拉雅,我听一些有声小说,一些心理学,一些历史评书,一些经融财经等等。这段时间让我明白了很多东西,让我再次回到社会的时候学会了怎么淡然处事,怎么管理情绪,怎么去规划自己。
2017年6月,我再次回到了工作岗位,工作时眼睛还是很不舒服。虽然很不想去面对,但是现实的一些原因,我不得不去工作。我边工作边考虑怎么转行去做一些其他的事情。例如,去做销售,去做一些体力活,回老家开个小店 . . .
2017年11月,我辞职了,辞去了技术的工作,开始了销售工作。由于没有销售经验,干的很吃力,我不懂得怎么找客户,不会打电话,不知道怎么向客户介绍产品。干了将近两个月,我还是放弃了。我重新考虑自己的职业发展,虽然我不能再回到技术岗位上了,但我还是热爱互联网这个行业。于是我决定,我要从事这个离技术最近的岗位,我要做产品。
2018年1月,我正式开始了产品相关的工作。其实我发现自己一直有一个产品的梦想,12年大一的时候,学习着怎么去建站,怎么去运营推广网站,16年小程序火的时候,熬夜去看了微信的开发文档,想去做一款小游戏,17年年初的时候,想做一款别致的社交APP,熟人间的匿名社交,当初和朋友同事谈了想法后,好几个人都想和我一起去开发这款应用,我都开始准备写文档做原型了,可是后面因为眼睛的问题便放弃了。
自从做了产品经理后,发现很多事情并不是自己想的那么简单。以前关于产品经理的理解都停留在“术”的层面,以为懂了一些画原型的工具就以为可以做产品经理了。现在逐渐明白“道”才是产品经理的关键。
关于产品,我一直认为,一个好的产品,它要满足企业的需求,它能解决用户需求,有黏性,有良好的交互体验。在这半年多时间里,我也一直往这个方向学习,理解并辅助公司的发展战略,学习挖掘用户需求,分析需求,管理需求,优化业务流程,保证良好的交互效果,分析运营数据,提高用户黏性。
努力去做好一个产品经理,努力去做好一个产品。不求可以改变世界,只想把事情做成,让用户更满意,但求可以为社会创造一点价值。
React 官方
官网地址:http://facebook.github.io/react/
Github地址:https://github.com/facebook/react
学习React之前,我们先了解一下它的设计思想,它与如今其他热门的前端框架有什么不同?它能为我们的开发解决哪些痛点?
1、React 设计思想
2、React的设计哲学 - 简单之美
3、颠覆式前端UI开发框架:React
可以结合一些简单demo去看文章,例如你在看阮一峰的React 入门实例教程时,可结合他写的入门demo,或官方给的demo。当然你也要边学习边自己去写一些简单demo,去改改别人写的一些React 项目。一定要多动手。
1、React 入门实例教程-阮一峰:建议先看demo
2、一看就懂的ReactJs入门教程(精华版)
3、React 教程-菜鸟教程:安装那节好像有点错
4、React 入门,5个常用DEMO展示
5、如何学习React
6、给新手的 React&Webpack 上手教程
7、ReactJS 傻瓜教程
8、React 最简单的入门应用项目
1、官方入门 demo:可结合官方的入门文档
2、入门 demo-阮一峰:结合入门文章
3、模仿知乎界面的一个简单React demo:结合 ReactJS中文基础视频教程-爱酷
一定要边看边写,不要囫囵吞枣的看一遍就好了。
1、React入门-慕课网
2、ReactJS中文基础视频教程-爱酷
3、ReactJS中文视频教程
4、React教程- 汇智网
了解React开发流程,作者的编码思路,写作规范。
1、React实战–打造画廊应用(上)
2、React实战–打造画廊应用(下)
3、ReactJS中文基础视频教程
4、构建实时聊天应用
开发其实不用详细去全看,在你做项目时,遇到不懂的就去查看一下文档,我认为这样效率更高一点。当然你有时间也可以一步步去阅读。
在学习中我们会遇到 一些问题,可以去社区或一些网站寻找答案,下面推荐一些好的React 社区和学习网站。
1、React中文社区
2、React 中文索引
2、React知识库
3、A quick start to React
4、stack overflow
5、知乎 React 话题
6、segmentfault React 话题
React是一款非常优秀的前端框架,你要发挥它完全的性能,你就要结合其他一些技术,例如webpack、redux、react-router等。
1、React 技术栈系列教程
2、百度母婴技术团队—基于Reactjs实现webapp
3、Building a React Universal Blog App
4、React为啥非得使用immutable.js
5、React Server Side Rendering 解决 SPA 应用的 SEO 问题
6、webpack官方文档
7、Webpack 中文指南
8、webpack一小时快速入门
9、使用webpack轻松构建你的第一个react开发框架
10、react-router
11、React Router 中文文档
12、React Router 官方 demo
13、Redux官网
14、Redux 中文文档
15、Redux 官方 demo
16、Redux 莞式教程
17、Redux 视频教程
18、redux 大法好
19、Flux 傻瓜教程
20、react+redux渲染性能优化原理
介绍一些国内外比较好的 React 开源项目。
国内:
1、阿里的 React 组件库
2、Ant Design
3、简易留言板
4、react-zhihu
5、React的扫雷游戏
6、在线聊天室
7、使用React技术栈开发SPA
8、阔论留言评论
9、React版cnode社区
国外:
1、Relax
2、SoundRedux
3、Gatsby
4、isomorphic500
5、NuclearMail
6、Picard
7、React Color
8、Sentry
9、react-hn
10、Perseus
项目地址:https://github.com/tsrot/react-zhihu
项目预览:http://blog.xieliqun.com/react-zhihu/
项目运行
|
|
|
|
|
|
你可以在npm的网站上找到相应插件的gulp配置写法。我配置的gulpfile.js
请切换分支到 product 分支
|
|
|
|
下载gulp-gh-pages插件
在gulpfile文件中添加配置gulp-gh-pages代码
将在分支中更新使用下列技术的版本
从作用域链的结构可以看出,在执行上下文的作用域链中,标识符所在的位置越深,读写速度就会越慢。
全局变量总是存在于执行上下文作用域链的最末端,因此在标识符解析的时候,查找全局变量是最慢的,并且全局变量将常驻内存直到程序退出,而局部变量会在函数运行完直接销毁。所以,在编写代码的时候应尽量少使用全局变量,尽可能使用局部变量。
一个好的经验法则是:如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。例如:
以上代码中document.getElementById('btn').className
被引用了三次,查找该变量必须遍历整个作用域链,直到最后在全局对象中才能找到document
,然后再去找它的方法和属性,这样严重的影响了程序性能。我们可以改为:
函数每次执行时对应的执行上下文都是独一无二的,所以多次调用同一个函数就会导致创建多个执行上下文,当函数执行完毕,执行上下文会被销毁。每一个执行上下文都和一个作用域链关联。一般情况下,在执行上下文运行的过程中,其作用域链只会被 with 语句和 catch 语句影响。
with语句是对象的快捷应用方式,用来避免书写重复代码。例如:
第一个alert使用的o对象里的href,所以弹出github.com?name=tsrot,第二个alert使用的就是全局的href。
当代码运行到with语句时,运行期上下文的作用域链临时被改变了。一个新的可变对象被创建,它包含了参数指定的对象的所有属性。这个对象将被推入作用域链的头部,这意味着函数的所有局部变量现在处于第二个作用域链对象中,因此访问代价更高了。此时的作用域链为:
另外一个会改变作用域链的是try-catch语句中的catch语句。当try代码块中发生错误时,执行过程会跳转到catch语句,然后把异常对象推入一个可变对象并置于作用域的头部。在catch代码块内部,函数的所有局部变量将会被放在第二个作用域链对象中。
一个函数只要内部函数未销毁(内部函数存在被调用的可能),这个函数就不会销毁,将一直存在于内存中,只有所有内部函数都销毁了,并所有的业务代码都已执行完,这个函数才会被释放。我们看看最常见的闭包问题:
当点击li标签时,弹出的一直都是length的大小。这是一个比较经典的错误。为什么会这样呢?
由于show的内部函数(click事件处理程序时刻有调用可能),所以show的作用域链不能被销毁(只能页面卸载是销毁),i的值一直保持for循环执行完后的length值,此时的click的函数只是进行了声明而未运行,当click触发的时候,函数才开始执行,这个时候i的值已经是length了。所以每次触发onclick的时候才会alert length。我们进行改一下:
为什么这样就行了呢,这时候onclick引用的变量变成了n,而由于立即执行函数的原因,每个onclick函数在作用域链中分别保持着对应的n(0~length-1),这时候就可以了。
闭包会使子函数保持其作用域链的所有变量及函数与内存中,内存消耗很大,在使用的时候尽量销毁父函数不再使用的变量。你经常访问一些范围之外的标识符,每次访问都将导致一些性能损失。
]]>作用域,在维基百科上解释是:在电脑程序设计中,作用域(scope,或译作有效范围)是名字(name)与实体(entity)的绑定(binding)保持有效的那部分计算机程序。
简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种,局部作用域又称为函数作用域。
在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:
|
|
|
|
一般情况下,window对象的内置属性都拥有全局作用域,例如window.name、window.location、window.top等等。
局部作用域在函数内创建,在函数内可访问,函数外不可访问。
了解作用域链之前我们要知道一下几个概念:
在JavaScript引擎解析JavaScript代码的时候,首先,JavaScript引擎会把变量和函数的声明提前进行预解析,然后再去执行其他代码。
变量声明:变量的声明只有一种方式,那就是用var
关键字声明,直接赋值不是一种声明方式。这仅仅是在全局对象上创建了新的属性(而不是变量)。它们有一下区别:
(1)因为它只是一种赋值,所以不会声明提前
(2)直接赋值形式是在执行阶段创建
(3)变量不能删除(delete),属性可以删除
但是,这里有一个意外情况,就是在“eval”的上下文中,变量是可以删除的:
有些debug工具也是可以删除的,因为它们使用了 eval()方法来执行代码的。
函数声明:函数的声明有三种方式
(1)function name( ){ }直接创建方式
(2)new Funtion构建函数创建
(3)给变量赋值匿名函数方法创建
后面两种方法,在声明前访问时,返回的都是一个undefined的变量。当然,在声明后访问它们都是一个function的函数。
注意:如果变量名和函数名声明时相同,函数优先声明。
函数的的生命周期分为创建和执行两个阶段。
在函数创建阶段,JS解析引擎进行预解析,会将函数声明提前,同时将该函数放到全局作用域中或当前函数的上一级函数的局部作用域中。
在函数执行阶段,JS引擎会将当前函数的局部变量和内部函数进行声明提前,然后再执行业务代码,当函数执行完退出时,释放该函数的执行上下文,并注销该函数的局部变量。
英文解释:
AO:Activetion Object(活动对象)
VO:Variable Object(变量对象)
VO对应的是函数创建阶段,JS解析引擎进行预解析时,所有的变量和函数的声明,统称为Variable Object。该变量与执行上下文相关,知道自己的数据存储在哪里,并且知道如何访问。VO是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的以下内容:
举个例子:
AO对应的是函数执行阶段,当函数被调用执行时,会建立一个执行上下文,该执行上下文包含了函数所需的所有变量,该变量共同组成了一个新的对象就是Activetion Object。该对象包含了:
举个例子:
现在我们回到主题,作用域链。
当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)来保证对执行环境有权访问的变量和函数的有序访问。作用域第一个对象始终是当前执行代码所在环境的变量对象(VO)。
假设函数是在全局作用域中创建的,在函数a创建的时候,它的作用域链填入全局对象,全局对象中有所有全局变量,此时的全局变量就是VO。此时的作用域链就是:
|
|
如果是函数执行阶段,那么将其activation object(AO)作为作用域链第一个对象,第二个对象是上级函数的执行上下文AO,下一个对象依次类推。
例如,调用add后的作用域链是:
|
|
在函数运行过程中标识符的解析是沿着作用域链一级一级搜索的过程,从第一个对象开始,逐级向后回溯,直到找到同名标识符为止,找到后不再继续遍历,找不到就报错。
看过上面的内容后,可能还有人不懂,我再通熟易懂的解释一遍,先举个例子:
上面代码的输出结果为”60″,函数bar可以直接访问”z”,然后通过作用域链访问上层的”x”和”y”。此时的作用域链为:
未完待续。。。
]]>
Yeoman是一个比较好的前端解决方案,它优化了前端开发的工作流,让前端开发人员更加专注业务代码的开发,像什么项目构建、代码校验、项目测试等,这些都交给Yeoman来做。
Yeoman中文
1、中文翻译(可能有些地方翻译的很粗糙)
2、提高页面加载速度
3、使用 google 字体镜像资源
4、优化国内 youtube 视频不能加载
欢迎访问 Yeoman中文,如有错误欢迎指正。
]]>以前我一直在用nitrous.io的在线IDE,它是一个国外的在线IDE,访问有点慢,一旦网络不好就掉线,挺好的地方就是,它每个月有50个小时的免费使用。coding.net相当于是一个国内版的github,也是一个远程的git仓库,它有个在线IDE还挺好用的。有终端命令面板、支持vim和 Emacs的编辑器、在线运行环境、支持git。
下面进入主题。
nvm是nodejs版本管理工具。可以在多个nodejs版本中进行切换,降低了升级nodejs时的成本。
下载nvm,直接在终端面板把它clone过来就行了。为了不影响项目目录,我们把它clone在项目根目录的同级目录。
接下来,进入nvm目录
安装nvm
安装完后,让系统自动执行它
现在就可以使用nvm命令了,查看一下help
查看可以安装的nodejs版本,这里将会输出一大堆可供安装的nodejs版本
选择一个进行安装,我安装的是v4.5.0
当然你可以安装多个版本,例如我还要安装最新版本,测试一下它的新特性
当你想切换回原先稳定版本时,你可以
安装完node,你就可以使用node和npm了。你可以安装一些自动化工具啊,一些插件啊什么的。
1、这些在线IDE虽然挺方便的,但毕竟没有本地的好,还有一些安全和网络限制的问题,另外到后面可能还要收费。
2、nvm问题,因为coding没有给用户root权限,不能够执行source /root/nvm/nvm.sh,让nvm每次启动项目自动执行。所以你每次在运行node前都必须先执行一下nvm。
|
|
name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面(可以是不同域的)时,name 的属性值依旧保持不变(只要不重新赋值)。name属性的值虽然不变,但对它的访问还是受到同域原则,不允许访问。所以我们要把iframe重新定向回原域,这样name的值也没变,并且可以访问了。
在最顶层,name 属性是不安全的,对于所有后续页面,设置在 name 属性中的任何信息都是可获得的。然而 windowName 模块总是在一个 iframe 中加载资源,并且一旦获取到数据,或者当你在最顶层浏览了一个新页面,这个 iframe 将被销毁,所以其他页面永远访问不到 window.name 属性。
为了方便以后的使用,我们把window.name进行一下封装。
|
|
假设我现在在http://127.0.0.1:8080 ,我有一个页面叫做a.html,现在我想获取http://127.0.0.1:9090 上的b.html的数据。
a.html
b.html
跨域是什么,我就不详细解释了,我相信你在看这篇文章前就已经了解的差不多了。现在我就直接进入实战阶段。
两个服务器:
先建立两个不同域的测试环境。我用http-server(一个node服务器插件)建立了两个不同端口的本地服务器。
两个页面:
在http://127.0.0.1:8080 中新建a.html,在http://127.0.0.1:9090 中新建b.html。
postMessage允许用户在两个窗口或frame之间传递数据,无论这个window对象是不是同源都能发送。
首先我们先在a.html中建立一个iframe。
|
|
当iframe加载完时,发送数据
|
|
postMessage包括两个参数data和url,data为发送的数据,url为发送地址。
html5新增了onmessage事件,它和onclick之类用法差不多。当窗口或frame接收到postMessage发送过来的数据时,将触发onmessage事件。
|
|
该事件接收一个event对象,这个对象有三个属性,分别为source,origin,data。
source: 消息源,消息的发送窗口/iframe。
origin:消息源的URI(可能包含协议、域名和端口),用来验证数据源。
data:发送方发送给接收方的数据。
这个例子是这样的,a页面中有一个iframe,这个iframe是另一个域的b页面。当b加载完的时候,让它去给iframe里的页面发送一条信息。然后里面的页面立即回复已经接收到信息,然后再等三秒,回复a所请求的数据。
a.html
|
|
b.html
|
|
在读这篇文章之前,你应该去在自己的脑海问几个问题:
1、什么是原型?
2、什么事原型链?
3、prototype与__proto__有什么不同,有什么联系?
4、constructor与面两个有什么联系,怎么用?
如果你把上面这四个问题都解决了,那你就真正了解了JS的原型和原型链。接下来,咱们一个一个问题去解决。
JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object ,Function 是JS自带的函数对象。每个对象都有原型(null和undefined除外),你可以把它理解为对象的默认属性和方法。
你可以把下面的代码在浏览器打印出来看一下。
|
|
Object:Object是一个函数对象,Object的原型就是一个Object对象,它里面存在着一些对象的方法和属性,例如最常见的toString方法。
新建对象:用new Object或者{}建的对象是普通对象,它没有prototype属性,只有__proto__属性,它指向Object.prototype。
Array:Array也是一个函数对象,它的原型就是Array.prototype,它里面存在着一些数组的方法和属性,例如常见的push,pop等方法。
Function:Function也是一个函数对象,但它有点特殊,它的原型就是一个function空函数。
自定义函数:它的原型就是你给它指定的那个东西。如果你不指定,那它的原型就是一个Object.prototype。
在 javaScript 中,每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototype chain)。
JavaScript 对象是动态的属性“包”(指其自己的属性)。JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
|
|
当你用new Object或者直接定义一个对象时,它的原型链就是:
o ==》 Object.prototype ==》 null
但你访问o上没有的属性或方法时,JS会往Object.prototype上寻找该属性和方法。如果有则直接返回,如果没有,方法则报错,这个方法未定义,属性则返回undefined。
|
|
当你用构造函数(构造函数我们一般首字母大写)建立一个对象时,它的原型链就是:
tsrot ==》 Person.prototype ==》 Object.prototype ==》 null
如果没有定义Person.prototype这一环,则直接跳到下一环。
来点更复杂的。
当你需要父类的属性和方法时,你可以把它的原型指向父类的原型。此时的原型链就是:
child ==》 Parent.prototype ==》 Object.prototype ==》 null
|
|
数组也是一个对象,不过它是由Array构造函数new而来的,所以它的原型链就是:
arr ==》 Array.prototype ==》 Object.prototype ==》 null
|
|
fun是一个函数对象,它是由Function构造函数new而来的,所以它的原型链就是:
fun ==》 Function.prototype ==》 Object.prototype ==》 null
fun它没有name属性,但是Function它有,所以这个name就是Function原型上的。
在Javascript中,每个函数都有一个原型属性prototype指向自身的原型,而由这个函数创建的对象也有一个__proto__属性指向这个原型,而函数的原型是一个对象(函数点prototype也是一个普通对象,Function.prototype除外,它是函数对象,但它很特殊,他没有prototype属性),所以这个对象也会有一个__proto__指向自己的原型,这样逐层深入直到Object对象的原型,这样就形成了原型链。普通对象没有prototype,但有__proto__属性。
|
|
JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype。
普通对象的__proto__
构造对象的__proto__
数组的__proto__
函数的__proto__
原型对象prototype中都有个预定义的constructor属性,用来引用它的函数对象。这是一种循环引用:
|
|
用构造函数创建的对象,它的constructor属性就是它的构造函数。
1、JavaScript Prototype Chains
2、Understanding JavaScript Prototypes
3、继承与原型链
Arguments对象是一个伪数组对象,它有length属性,可以arguments[i]来访问对象中的元素,但它不能用数组的一些方法,例如push,pop,slice等。
Arguments的length属性,表示function函数实际所传参数的个数。函数名点length可以获取函数期望的传参个数。
|
|
Arguments对象的参数访问可以用arguments[i]来访问函数所传的参数。
|
|
Arguments的callee属性可以调用函数本身,当函数正在执行时才可调用,可以实现方法的递归调用。
|
|
Function对象的caller属性可以指向当前函数的调用者,当调用者函数正在执行时才可调用,
|
|
方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。
|
|
|
|
|
|
这样的好处就是可以实现匿名函数的递归调用。
|
|
比如说,我想判断你传给我的一些数字的大小,取出最大的那个
|
|
要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数。所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称。
在JavaScript中,有三种常用的绑定事件的方法:
我们可以在DOM元素上绑定onclick、onmouseover、onmouseout、onmousedown、onmouseup、ondblclick、onkeydown、onkeypress、onkeyup等。好多不一一列出了。如果想知道更多事件类型请查看,DOM事件。
|
|
在JavaScript代码中(即script
标签内)绑定事件可以使JavaScript代码与HTML标签分离,文档结构清晰,便于管理和开发。
|
|
绑定事件的另一种方法是用 addEventListener() 或 attachEvent() 来绑定事件监听函数。下面详细介绍,事件监听。
关于事件监听,W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段。
起初Netscape制定了JavaScript的一套事件驱动机制(即事件捕获)。随即IE也推出了自己的一套事件驱动机制(即事件冒泡)。最后W3C规范了两种事件机制,分为捕获阶段、目标阶段、冒泡阶段。IE8以前IE一直坚持自己的事件机制(前端人员一直头痛的兼容性问题),IE9以后IE也支持了W3C规范。
语法:
event : (必需)事件名,支持所有DOM事件。
function:(必需)指定要事件触发时执行的函数。
useCapture:(可选)指定事件是否在捕获或冒泡阶段执行。true,捕获。false,冒泡。默认false。
注:IE8以下不支持。
语法:
event:(必需)事件类型。需加“on“,例如:onclick。
function:(必需)指定要事件触发时执行的函数。
|
|
1、可以绑定多个事件。
常规的事件绑定只执行最后绑定的事件。
|
|
两个事件都执行了。
2、可以解除相应的绑定
|
|
事件委托就是利用冒泡的原理,把事件加到父元素或祖先元素上,触发执行效果。
|
|
上面只是个例子,代码尽可能的简化了。在实际的代码中 我们可能用到jQuery的live()、delegate()、bind()、on()等。
1、提高JavaScript性能。事件委托可以显著的提高事件的处理速度,减少内存的占用。实例分析JavaScript中的事件委托和事件绑定,这篇文章写得还不错。
传统写法
|
|
事件委托
2、动态的添加DOM元素,不需要因为元素的改动而修改事件绑定。
传统写法
点击item1到item3都有事件响应,但是点击item4时,没有事件响应。说明传统的事件绑定无法对动态添加的元素而动态的添加事件。
事件委托
当点击item4时,item4有事件响应。说明事件委托可以为新添加的DOM元素动态的添加事件。
语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
arg1 … argN为被调用方法的传参。
语法:apply([thisObj[,argArray]])
定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明:apply的第一个参数thisObj和call方法的一样,第二个参数argArray为一个传参数组。thisObj如果未传,那么 Global 对象被用作 thisObj。
在ECMAScript5中扩展了叫bind的方法(IE6,7,8不支持)
语法:bind([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明:bind的thisObj参数也和call方法一样,thisObj如果未传,那么 Global 对象被用作 thisObj。arg1 … argN可传可不传。如果不传,可以在调用的时候再传。如果传了,调用的时候则可以不传,调用的时候如果你还是传了,则不生效。例如:
|
|
|
|
1、call的arg传参需一个一个传,apply则直接传一个数组。
2、call和apply直接执行函数,而bind需要再一次调用。
|
|
|
|
|
|
|
|
|
|
大家都知道ajax并非一种新的技术,而是几种原有技术的结合体。它由下列技术组合而成。
在上面几中技术中,除了XmlHttpRequest对象以外,其它所有的技术都是基于web标准并且已经得到了广泛使用的,XMLHttpRequest虽然目前还没有被W3C所采纳,但是它已经是一个事实的标准,因为目前几乎所有的主流浏览器都支持它。
Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。原生创建ajax可分为以下四步。
所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。
创建 XMLHttpRequest 对象的语法:
老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象:
为了应对所有的现代浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象。如果支持,则创建 XMLHttpRequest 对象。如果不支持,则创建 ActiveXObject :
初始化该XMLHttpRequest对象,接受三个参数:
第一个参数表示请求类型的字符串,其值可以是GET或者POST。
GET请求:
POST请求:
第二个参数是要作为请求发送目标的URL。
第三个参数是true或false,表示请求是以异步还是同步的模式发出。(默认为true,一般不建议为false)
|
|
一般情况下,使用Ajax提交的参数多是些简单的字符串,可以直接使用GET方法将要提交的参数写到open方法的url参数中,此时send方法的参数为null或为空。
GET请求:
POST请求:
如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据:
|
|
onreadystatechange 事件:
当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。
readyState属性:
0:已经创建对象,但还没有调用open()方法。
1:已经调用open()方法,但还没有发送请求。
2:请求已经发送,标题和状态已经收到,并可用。
3:接收到来自服务器的响应。
4:接收完请求数据,表示已经完成请求。
status属性:
200:”OK”
404: 未找到页面
responseText:获得字符串形式的响应数据
responseXML:获得 XML 形式的响应数据
返回值一般为json字符串,可以用JSON.parse(xhr.responseText)转化为JSON对象。
demo.html
data.json
优点:
1、页面无刷新,用户体验好。
2、异步通信,更加快的响应能力。
3、减少冗余请求,减轻了服务器负担
4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。
缺点:
1、ajax干掉了back按钮,即对浏览器后退机制的破坏。
2、存在一定的安全问题。
3、对搜索引擎的支持比较弱。
4、破坏了程序的异常机制。
5、无法用URL直接访问。
###一、JavaScript为什么会有闭包这种东西
JavaScript没有像其它后端语言一样可以直接定义一个变量可供其它外部函数调用的关键字或者方法。于是就产生了闭包这种东西。举个例子:
|
|
如果是java,一个类的私有属性,可以通过公共的方法来获取,比如:
闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包的特点:
我的理解就是:让函数外部能调用函数内部变量的一个过程就是闭包。举个例子:
###三、闭包的用途
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。举个例子:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
思考1:修改下面函数使之输出数组内元素?
思考2:修改下面代码使之输出它想表达的结果
答案1
答案2
|
|
随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。
|
|
此时的变量name相当于window.name,因为调用sayHello函数的对象为window,相当于window.sayHello()。和下面两种情况是一样的:
下面的name相当于在window下赋值了两次,谁后面执行就取谁。如果把var name = “xieliqun”放到sayHello()后面,此时输出的就是 hello xieliqun。
注:当函数在DOM上调用时,未传入this,此时,this也指向window。当传入this时,this指向当前DOM input,例如下面情况:
|
|
函数还可以作为某个对象的方法调用,这时this就指这个上级对象。
所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。
call()、apply()都是函数对象的一个方法,它们的作用是改变函数的调用对象,它们的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。
apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。
如果把最后一行代码修改为
此时this就指向对象o了。
很多人不知道原生js也有bind()方法,一直以为bind()的方法只有jQuery有,我也是最近看别人博客知道的。其实原生的bind和jQuery的bind是不同的,原生的bind相当于apply和call。
下图代码中person.sayHello,相当于在window.person.sayHello,所以this指向window。
用apply和call调用时,函数将立即执行
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。
|
|
当return null和undefined时
|
|
下面我简单介绍一下我的入坑经历:
1、这步还算顺利(前提是你安装了nodeJS,过程可能有点慢,看网络环境和人品了。如果
长时间停留在某个地方,Ctrl+C 暂停它,再运行一次)
2、这步也还算顺利,就是有点慢。
如果你仅仅作为一个前端开发者,走到这步就可以在browser 运行起来了,但作为一个极
客,怎能止于这步。
3、接下来就进入大坑了
4、接下来就是漫长且苦逼的填坑经历了。
…………………………………………………………………
github地址:ionic初学者文档
或者你可以直接clone