Aomine

Aomine 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

喜欢web开发,初学阶段,希望未来能成为厉害的工程师~

个人动态

Aomine 赞了文章 · 2015-03-02

黑客马拉松促进编程和公民思想

编者注:开放政府数据给黑客们为民服务,不得不给这样开明的镇长点赞~


clipboard.png

2月21日,迈阿密戴德镇政府在Miami Ad School举办的编程比赛中开放了政府数据库。

2015年Code Across 的主题围绕21世纪的政府。 这次编程比赛时间与国际数据开放日2月21日吻合。 这次活动以数字化的方式回答了关于政府和社区的常见问题,为迈阿密戴德镇的健康状况、人口资源、社会服务和其他公民服务建立了一个开源指向。

镇长Carlos Gimenez介绍了能帮助迈阿密戴德镇提升数字化进程的Code for America fellows。

“这是迈阿密戴德镇的成为技术和创新枢纽的迹象“,Gimenez在一份声明中说道。 “作为我们积极开放数据政策的一部分,Code for America fellows将帮助我们提供更透明的政府,用科技使我们更高效,并且更亲近市民”

很多人把“黑客”联想到闯入电脑文件和窃取信息。 然而,根据opengovdata.io,有一种黑客意味着可以改变传统方法来解决问题。 这就是所谓的公民黑客。

在周六的Code for America Hackathon上,一群人运用已知的数据和观点解决了迈阿密戴德镇居民关于政府和社区居民的常见问题。

最常问到的问题是——哪里是迈阿密戴德镇发生狗咬事件最多的地方。 根据狗咬事件的数据,公民黑客Don Llopis 创建了一个地图来说明了狗咬事件发生得最高和最低的位置。 Llopis是一个安卓开发者,他分享了在黑客马拉松活动的经验。

“我认为,政府提供这些数据给我们的做法很伟大。”Llopis说。 “能够操纵可视化部分和分析实时数据太棒了。”

Gimenez 认为迈阿密戴德镇开放数据库可能会对年轻一代有重要意义。

“我当上镇长的时候,我意识到,戴德镇未来青壮年的就业机会将取决于不断发展的技术、创新和地方企业”。

“这就是为什么我们致力于把迈阿密戴德镇引向数据开放的路上。”

黑客们在twitter上通过“#CodeAcross”话题向世界分享他们的成果。

英文原文: Hackathon promotes coding and civic ideas
SegmentFault整理编译

查看原文

赞 1 收藏 1 评论 0

Aomine 赞了文章 · 2015-02-06

HTML5 Web Speech API,让网站更有趣

Web API 变得越来越丰富,其中一个值得注意的是Web Speech API。传统的网站只能“说”,这个API的出现,让网站能“倾听”用户。这个功能已经开放了一系列的用法,非常棒。

在这篇文章中,我们将看一下这项技术和建议的用法,以及如何用它来增强用户体验的一些好例子。

clipboard.png

声明:本技术比较前沿,目前该规范是W3C的“非官方编辑器的征求意见稿”(截至2014年6月6日)。它的使用方法可能和本文中的代码片有所不同。查看代码规范和发布前的测试是很有必要的。

语音合成 Speech Synthesis

该API分为两部分。首先,让我们来看看语音的合成部分——说话。如果你的网站有一些文字内容——文章主体、表单、输入框、标签等——你可以运行一些有趣的功能,设备就会把文字读给用户听。

来看看做到这一点所需要的代码。首先创建SpeechSynthesisUtterance接口的新实例。然后指定要阅读的文本。再把这个实例添加到队列中,告诉浏览器什么时候说话。

下面的speak函数里完成了上面所述的功能 ,把想要朗读的内容作为参数。

function speak(textToSpeak) {
   //创建一个 SpeechSynthesisUtterance的实例
   var newUtterance = new SpeechSynthesisUtterance();

   // 设置文本
   newUtterance.text = textToSpeak;

   // 添加到队列
   window.speechSynthesis.speak(newUtterance);
}

现在我们需要做的就是调用这个函数,并传入我们想要朗读的内容:

speak('Welcome to Smashing Magazine');

SpeechSynthesisUtterance还有开始、暂停、停止功能,还能设置语言、速度、声音。停止、启动或暂停都触发一个事件,开发者可以编写这个事件来完成很多有趣的事情。

目前,语音合成只有Chrome和Safari(包括桌面和移动设备版)支持。此外,通过API提供给用户的声音在很大程度上取决于操作系统。谷歌有自己的一套给Chrome的默认声音,可以在Mac OS X,Windows和Ubuntu上使用。Mac OS X的声音也可用,所以和OSX的Safari的声音一样。你可以通过开发者工具的控制台看有哪种声音可用。

window.speechSynthesis.getVoices();

如果你使用OS X,可以用“Zarvox”声音

语音识别 Speech Recognition

Web Speech API另一部分是语音识别,它能够识别用过从麦克风或网站应用获取的语音。

让我们通过一些代码运行。这一次,我们将创建SpeechRecognition的新实例。因为这部分只得到了Chrome的支持,所以要添加WebKit的前缀。

var newRecognition = webkitSpeechRecognition();

peechRecognition有相当多的属性。比如状态是可连续的,浏览器在没有接收到声音的一段时间后默认把状态设为false,如果你想继续听,可以设为true

newRecognition.continuous = true;

开启和停止语音识别,使用start()stop()

// 开始
newRecognition.start();

// 停止
newRecognition.stop();

还可以绑定很多事件,例如:soundstartspeechstartresulterror看看这个demo

使用场景举例

听写

目前,Speech API最常见的用法是听写和读取。也就是用户通过麦克风说话,设备把语音翻译成文字(看看Chrome开发团队做的demo),或者设备读取文字转化成语音。

设备能说话这是非常有用的功能。设想一下,当你早上起床的时候,镜子告诉你今天的天气,这多么神奇。

很多汽车都有语音系统,在你开车的时候给你导航。设想一下,当你在开车的时候,浏览器把你想要的内容读给你听,多么方便。

声音控制

听写可以很容易地变成语音控制。正如上面的例子,我们可以通过语音导航。如果把这个功能加入到网络电视的浏览器中,将会有更多有意思的实现。

我的同事做了个网球应用,在他打球的时候,它的应用会把他的分数读出来。

翻译

未来翻译会变得很不一样。一个人说了一段话,设备就翻译成对方的语言并读出。

限制

离线是需要注意的问题。目前API的实现是浏览器把数据发送到远端服务器,再把处理好的数据返回。没有网络就无法实现功能。


英文原文: Enhancing User Experience With The Web Speech API
由SegmentFault整理翻译

查看原文

赞 3 收藏 25 评论 4

Aomine 关注了标签 · 2014-07-30

android

Android(安卓或安致)是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

简介

  Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统、中间件、用户界面和应用软件组成。 

  系统架构

  android的系统架构和其操作系统一样,采用了分层的架构。从架构图看,android分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。

  应用程序

  Android会同一系列核心应用程序包一起发布,该应用程序包包括客户端,SMS短消息程序,日历,地图,浏览器,联系人管理程序等。所有的应用程序都是使用JAVA语言编写的。

  应用程序框架

  开发人员也可以完全访问核心应用程序所使用的API框架。该应用程序的架构设计简化了组件的重用;任何一个应用程序都可以发布它的功能块并且任何其它的应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性)。同样,该应用程序重用机制也使用户可以方便的替换程序组件。

  隐藏在每个应用后面的是一系列的服务和系统, 其中包括;

  丰富而又可扩展的视图(Views),可以用来构建应用程序, 它包括列表(lists),网格(grids),文本框(text boxes),按钮(buttons), 甚至可嵌入的web浏览器。

  内容提供器(Content Providers)使得应用程序可以访问另一个应用程序的数据(如联系人数据库), 或者共享它们自己的数据

  资源管理器(Resource Manager)提供 非代码资源的访问,如本地字符串,图形,和布局文件( layout files )。

  通知管理器 (Notification Manager) 使得应用程序可以在状态栏中显示自定义的提示信息。

  活动管理器( Activity Manager) 用来管理应用程序生命周期并提供常用的导航回退功能。

  有关更多的细节和怎样从头写一个应用程序,请参考 如何编写一个 Android 应用程序。

  系统运行库

  Android 包含一些C/C++库,这些库能被Android系统中不同的组件使用。它们通过 Android 应用程序框架为开发者提供服务。以下是一些核心库:

  * 系统 C 库 - 一个从BSD继承来的标准 C 系统函数库( libc ), 它是专门为基于 embedded linux的设备定制的。

  * 媒体库 - 基于PacketVideo OpenCORE;该库支持多种常用的音频、视频格式回放和录制,同时支持静态图像文件。编码格式包括MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 。

  * Surface Manager - 对显示子系统的管理,并且为多个应用程序提 供了2D和3D图层的无缝融合。

  * LibWebCore - 一个最新的web浏览器引擎用,支持Android浏览器和一个可嵌入的web视图。

  应用程序组件

  Android开发四大组件分别是:活动(Activity): 用于表现功能。服务(Service): 后台运行服务,不提供界面呈现。广播接收器(BroadcastReceiver):用于接收广播。内容提供商(Content Provider): 支持在多个应用中存储和读取数据,相当于数据库。

  活动

  Android 中,Activity 是所有程序的根本,所有程序的流程都运行在Activity 之中,Activity可以算是开发者遇到的最频繁,也是Android 当中最基本的模块之一。在Android的程序当中,Activity 一般代表手机屏幕的一屏。如果把手机比作一个浏览器,那么Activity就相当于一个网页。在Activity 当中可以添加一些Button、Check box 等控件。可以看到Activity 概念和网页的概念相当类似。

  一般一个Android 应用是由多个Activity 组成的。这多个Activity 之间可以进行相互跳转,例如,按下一个Button 按钮后,可能会跳转到其他的Activity。和网页跳转稍微有些不一样的是,Activity 之间的跳转有可能返回值,例如,从Activity A 跳转到Activity B,那么当Activity B 运行结束的时候,有可能会给Activity A 一个返回值。这样做在很多时候是相当方便的。

  当打开一个新的屏幕时,之前一个屏幕会被置为暂停状态,并且压入历史堆栈中。用户可以通过回退操作返回到以前打开过的屏幕。我们可以选择性的移除一些没有必要保留的屏幕,因为Android会把每个应用的开始到当前的每个屏幕保存在堆栈中。

  服务

  Service 是android 系统中的一种组件,它跟Activity 的级别差不多,但是他不能自己运行,只能后台运行,并且可以和其他组件进行交互。Service 是没有界面的长生命周期的代码。Service 是一种程序,它可以运行很长时间,但是它却没有用户界面。这么说有点枯燥,来看个例子。打开一个音乐播放器的程序,这个时候若想上网了,那么,我们打开Android 浏览器,这个时候虽然我们已经进入了浏览器这个程序,但是,歌曲播放并没有停止,而是在后台继续一首接着一首的播放。其实这个播放就是由播放音乐的Service进行控制。当然这个播放音乐的Service也可以停止,例如,当播放列表里边的歌曲都结束,或者用户按下了停止音乐播放的快捷键等。service 可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD 卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的。

  开启service有两种方式:

  (1) Context.startService():Service会经历onCreate -> onStart(如果Service还没有运行,则android先调用onCreate()然后调用onStart();如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次 );stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。 注意,多次调用Context.startservice()不会嵌套(即使会有相应的onStart()方法被调用),所以无论同一个服务被启动了多少次,一旦调用Context.stopService()或者stopSelf(),他都会被停止。补充说明:传递给startService()的Intent对象会传递给onStart()方法。调用顺序为:onCreate --> onStart(可多次调用) --> onDestroy。

  (2) Context.bindService():Service会经历onCreate() --> onBind(),onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind --> onDestroyed相应退出,所谓绑定在一起就共存亡了。[20]

  广播接收器

  在Android 中,Broadcast 是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver 是对发送出来的Broadcast进行过滤接受并响应的一类组件。可以使用BroadcastReceiver 来让应用对一个外部的事件做出响应。这是非常有意思的,例如,当电话呼入这个外部事件到来的时候,可以利用BroadcastReceiver 进行处理。例如,当下载一个程序成功完成的时候,仍然可以利用BroadcastReceiver 进行处理。BroadcastReceiver不能生成UI,也就是说对于用户来说不是透明的,用户是看不到的。BroadcastReceiver通过NotificationManager 来通知用户这些事情发生了。BroadcastReceiver 既可以在AndroidManifest.xml 中注册,也可以在运行时的代码中使用Context.registerReceiver()进行注册。只要是注册了,当事件来临的时候,即使程序没有启动,系统也在需要的时候启动程序。各种应用还可以通过使用Context.sendBroadcast () 将它们自己的intent broadcasts广播给其他应用程序。

  注册BroadcastReceiver有两种方式:

  (1)在AndroidManifest.xml进行注册。这种方法有一个特点即使你的应用程序已经关闭了,但这个BroadcastReceiver依然会接受广播出来的对象,也就是说无论你这个应用程序时开还是关都属于活动状态都可以接受到广播的事件;

  (2)在代码中注册广播。

  第一种俗称静态注册,第二种俗称动态注册,这两种注册Broadcast Receiver的区别:

  动态注册较静态注册灵活。实验证明:当静态注册一个Broadcast Receiver时,不论应用程序是启动与否。都可以接受对应的广播。

  动态注册的时候,如果不执行unregister Receiver();方法取消注册,跟静态是一样的。但是如果执行该方法,当执行过以后,就不能接受广播了。

  内容提供

  Content Provider 是Android提供的第三方应用数据的访问方案。

  在Android中,对数据的保护是很严密的,除了放在SD卡中的数据,一个应用所持有的数据库、文件等内容,都是不允许其他直接访问的。Andorid当然不会真的把每个应用都做成一座孤岛,它为所有应用都准备了一扇窗,这就是Content Provider。应用想对外提供的数据,可以通过派生Content Provider类, 封装成一枚Content Provider,每个Content Provider都用一个uri作为独立的标识,形如:content://com.xxxxx。所有东西看着像REST的样子,但实际上,它比REST 更为灵活。和REST类似,uri也可以有两种类型,一种是带id的,另一种是列表的,但实现者不需要按照这个模式来做,给你id的uri你也可以返回列表类型的数据,只要调用者明白,就无妨,不用苛求所谓的REST。

  另外,Content Provider不和REST一样只有uri可用,还可以接受Projection,Selection,OrderBy等参数,这样,就可以像数据库那样进行投影,选择和排序。查询到的结果,以Cursor(参见:reference/android/database/Cursor.html )的形式进行返回,调用者可以移动Cursor来访问各列的数据。

  Content Provider屏蔽了内部数据的存储细节,向外提供了上述统一的接口模型,这样的抽象层次,大大简化了上层应用的书写,也对数据的整合提供了更方便的途径。Content Provider内部,常用数据库来实现,Android提供了强大的Sqlite支持,但很多时候,你也可以封装文件或其他混合的数据。

  在Android中,Content Resolver是用来发起Content Provider的定位和访问的。不过它仅提供了同步访问的Content Provider的接口。但通常,Content Provider需要访问的可能是数据库等大数据源,效率上不足够快,会导致调用线程的拥塞。因此Android提供了一个AsyncQueryHandler(参见:reference/android/content/AsyncQueryHandler.html),帮助进行异步访问Content Provider。

  在各大组件中,Service和Content Provider都是那种需要持续访问的。Service如果是一个耗时的场景,往往会提供异步访问的接口,而Content Provider不论效率如何,都提供的是约定的同步访问接口。

软件开发

  Java方面

  Android支持使用Java作为编程语言来开发应用程序,而Android的Java开发方面从接口到功能,都有层出不穷的变化。考虑到Java虚拟机的效率和资源占用,谷歌重新设计了Android的Java,以便能提高效率和减少资源占用,因而与J2ME等不同。其中Activity等同于J2ME的MIDlet,一个 Activity 类(Class)负责创建视窗(Windows),一个活动中的Activity就是在 foreground(前景)模式,背景运行的程序叫做Service。两者之间通过由ServiceConnection和AIDL连结,达到复数程序同时运行效果。如果运行中的 Activity 全部画面被其他 Activity 取代时,该 Activity 便被停止(Stopped),甚至被系统清除(Kill)。

  View等同于J2ME的Displayable,程序人员可以通过 View 类与“XML layout”档将UI放置在视窗上,Android 1.5的版本可以利用 View 打造出所谓的 Widgets,其实Widget只是View的一种,所以可以使用xml来设计layout,HTC的Android Hero手机即含有大量的widget。至于ViewGroup 是各种layout 的基础抽象类(abstract class),ViewGroup之内还可以有ViewGroup。View的构造函数不需要再Activity中调用,但是Displayable的是必须的,在Activity 中,要通过findViewById()来从XML 中取得View,Android的View类的显示很大程度上是从XML中读取的。View 与事件(event)息息相关,两者之间通过Listener 结合在一起,每一个View都可以注册一个event listener,例如:当View要处理用户触碰(touch)的事件时,就要向Android框架注册View.OnClickListener。另外还有BitMap等同于J2ME的Image。   

关注 63479

Aomine 关注了标签 · 2014-07-30

java

Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaSE, JavaEE, JavaME)的总称。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

Java编程语言的风格十分接近 C++ 语言。继承了 C++ 语言面向对象技术的核心,Java舍弃了 C++ 语言中容易引起错误的指針,改以引用取代,同时卸载原 C++ 与原来运算符重载,也卸载多重继承特性,改用接口取代,增加垃圾回收器功能。在 Java SE 1.5 版本中引入了泛型编程、类型安全的枚举、不定长参数和自动装/拆箱特性。太阳微系统对 Java 语言的解释是:“Java编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言”。

版本历史

重要版本号版本代号发布日期
JDK 1.01996 年 1 月 23 日
JDK 1.11997 年 2 月 19 日
J2SE 1.2Playground1998 年 12 月 8 日
J2SE 1.3Kestrel2000 年 5 月 8 日
J2SE 1.4Merlin2002 年 2 月 6 日
J2SE 5.0 (1.5.0)Tiger2004 年 9 月 30 日
Java SE 6Mustang2006 年 11 月 11 日
Java SE 7Dolphin2011 年 7 月 28 日
Java SE 8JSR 3372014 年 3 月 18 日
最新发布的稳定版本:
Java Standard Edition 8 Update 11 (1.8.0_11) - (July 15, 2014)
Java Standard Edition 7 Update 65 (1.7.0_65) - (July 15, 2014)

更详细的版本更新查看 J2SE Code NamesJava version history 维基页面

新手帮助

不知道如何开始写你的第一个 Java 程序?查看 Oracle 的 Java 上手文档

在你遇到问题提问之前,可以先在站内搜索一下关键词,看是否已经存在你想提问的内容。

命名规范

Java 程序应遵循以下的 命名规则,以增加可读性,同时降低偶然误差的概率。遵循这些命名规范,可以让别人更容易理解你的代码。

  • 类型名(类,接口,枚举等)应以大写字母开始,同时大写化后续每个单词的首字母。例如:StringThreadLocaland NullPointerException。这就是著名的帕斯卡命名法。
  • 方法名 应该是驼峰式,即以小写字母开头,同时大写化后续每个单词的首字母。例如:indexOfprintStackTraceinterrupt
  • 字段名 同样是驼峰式,和方法名一样。
  • 常量表达式的名称static final 不可变对象)应该全大写,同时用下划线分隔每个单词。例如:YELLOWDO_NOTHING_ON_CLOSE。这个规范也适用于一个枚举类的值。然而,static final 引用的非不可变对象应该是驼峰式。

Hello World

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

编译并调用:

javac -d . HelloWorld.java
java -cp . HelloWorld

Java 的源代码会被编译成可被 Java 命令执行的中间形式(用于 Java 虚拟机的字节代码指令)。

可用的 IDE

学习资源

常见的问题

下面是一些 SegmentFault 上在 Java 方面经常被人问到的问题:

(待补充)

关注 104873

Aomine 关注了标签 · 2014-07-30

ios

iOS 是苹果公司为其移动产品开发的操作系统。它主要给 iPhone、iPod touch、iPad 以及 Apple TV 使用。原本这个系统名为 iPhone OS,直到2010年6月7日 WWDC 大会上宣布改名为 iOS。

系统结构

  iOS的系统结构分为以下四个层次:核心操作系统(the Core OS layer),核心服务层(the Core Services layer),媒体层(the Media layer),Cocoa 触摸框架层(the Cocoa Touch layer)。

发展历史

iOS最早于2007年1月9日的苹果Macworld展览会上公布,随后于同年的6月发布的第一版iOS操作系统,当初的名称为“iPhone 运行 OS X”。最初,由于没有人了解“iPhone 运行 OS X”的潜在价值和发展前景,导致没有一家软件公司、没有一个软件开发者给“iPhone 运行 OS X”开发软件或者提供软件支持。于是,苹果公司时任CEO斯蒂夫.乔布斯说服各大软件公司以及开发者可以先搭建低成本的网络应用程序(WEB APP)来使得它们能像iPhone的本地化程序一样来测试“iPhone runs OS X”平台。 

  1. 2007年10月17日,苹果公司发布了第一个本地化IPhone应用程序开发包(SDK),并且计划在2月发送到每个开发者以及开发商手中。

  2. 2008年3月6日,苹果发布了第一个测试版开发包,并且将“iPhone runs OS X”改名为”iPhone OS“。 

  3. 2010年2月27日,苹果公司发布iPad,iPad同样搭载了”iPhone OS”。这年,苹果公司重新设计了“iPhone OS”的系统结构和自带程序。 

  4. 2010年6月,苹果公司将“iPhone OS”改名为“iOS”,同时还获得了思科iOS的名称授权。 

  5. 2010年第四季度,苹果公司的iOS占据了全球智能手机操作系统26%的市场份额。

  6. 2011年10月4日,苹果公司宣布iOS平台的应用程序已经突破50万个。

  7. 2012年2月,应用总量达到552,247个,其中游戏应用最多,达到95,324个,比重为17.26%;书籍类以60,604个排在第二,比重为10.97%;娱乐应用排在第三,总量为56,998个,比重为10.32%。

  8. 2012年6月,苹果公司在WWDC 2012 上宣布了iOS 6,提供了超过 200 项新功能。

  9. 2013年9月11日凌晨苹果在秋季发布会上宣布iOS 7于9月18日正式推出,2013年9月19日凌晨1点开放免费下载更新。

  10. iOS 8于2014年9月17号向用户推送正式版。

  11. iOS 9于2015年9月16日正式推出。iOS 9系统比iOS8更稳定,功能更全面,而且还更加开放。iOS 9加入了更多的新功能,包括更加智能的Siri,新加入的省电模式。iOS 9为开发者提供5000个全新的API。

  12. 2015年12月9日,苹果正式推送了iOS 9.2,更新内容相当之多,修复BUG改善稳定性自然不必多说,还增加了很多新功能,比如邮件增加了Mail Drop功能可以发送大附件、iBooks开始支持3D Touch、Apple News新闻中的“热门报道”等等

关注 50507

Aomine 赞了回答 · 2014-07-30

大家第一个阅读的开源代码是什么?

语言:JavaScript
项目:jquery
特点:链式结构,大众化框架,对了解浏览器兼容性有不小帮助

关注 2 回答 47

Aomine 赞了回答 · 2014-04-22

你们是怎么分析框架或库的源码的?(前端)

我就拿JS说了
1.分析网站的JS
2.分析框架:
首先一定会用得比较熟了,然后去了解框架的基本原理/结构,网上各种搜资料和问人,然后自己尝试仿照写一个很简单的小框架。有时以为看懂了,也许是理解错的,只有实践了才知道正确答案。
拿我学习Jquery举例。Jquery是链式结构,那首先就得研究这个链式结构是如何做到的,其间上网去查/去问别人。了解了这个,我就开始自己尝试这写了一个这样的简单的链式框架,尝试着实现JQ的功能。抛开效率问题,我能完成大部分JQ的功能,从中学习到包括兼容性/如何调试代码/继承等知识。写的过程中会遇到问题,我就把JQ 2.0全部打印下来,在编辑器上根据各种跳转查看,理顺了逻辑,再记录到打印的纸上。很多东西是看不懂的,我就跳过,尽量把逻辑弄懂就行,然后自己想办法实现,这也是一个思考的过程。JQ源码有些注释,可以帮助理解。我写的时候也借鉴了学长写过的仿JQ的小框架,他的代码是压缩混淆过的,我读的时候费了很大劲。我写的这个尽量留了注释,有兴趣可以读下,有错欢迎指出。

关注 7 回答 7

Aomine 赞了回答 · 2014-04-22

解决Sublime Text 3中无法使用Git插件

ST3中无法正常使用git插件,无法add。建议换sublime git ,我现在就是用这个。功能齐全更强大。是带界面的,比git插件强大很多。免费的,偶尔会弹出购买框,可以选择性无视。
官网

关注 0 回答 1

Aomine 回答了问题 · 2014-03-04

解决一个像素占多少内存,占多少硬盘?

http://blog.csdn.net/zhuzhihai1988/article/details/8903115
取决于需要存储一个像素的多少信息,以及是否采用了压缩技术。
如果是非黑即白的二值图像,不压缩的情况下一个像素只需要1个bit。
如果是256种状态的灰度图像,不压缩的情况下一个像素需要8bit(1字节,256种状态)。
如果用256种状态标识屏幕上某种颜色的灰度,而屏幕采用三基色红绿蓝(RGB),不压缩的情况下一个像素需要占用24bit(3字节),这个就是常说的24位真彩色。
还有各种其他的存储方式,例如15bit、16bit、32bit
如果考虑到压缩,情况就更复杂了,是有损压缩还是无损压缩,具体采用哪种压缩算法,压缩参数参数设置等等都会影响到一个像素占用的存储空间。

关注 0 回答 1

Aomine 收藏了文章 · 2014-03-04

回调蛋糕 —— cake下顺序执行命令

cake是CoffeeScript自带的make工具,简单易用。不过有一个问题,因为Node.js默认是异步的,所以你很难保证执行顺序。

如何解决呢?其实用回调函数就可以。

例如,假定我们平时使用config.json(方便开发和测试),但是在发布NPM包的时候,希望发布config.json.example。这就要求我们在npm publish前后修改文件名——也就是说,要保证执行的顺序,不能出现文件名还没改好就发布的情况。如果用sh表达的话,就是:

mv config.json config.json.example
npm publish
mv config.json.example config.json

硬来的话,是这么写:

{spawn} = require 'child_process'

spawn 'mv', ['config.json', 'config.json.example']
spawn 'npm', ['publish']
spawn 'mv', ['config.json.example', 'congfig.json']

硬蛋糕可不好吃!这样是不行的,因为child_process.spawn是异步的。

所以,我们需要把上面的代码改成回调的形式,确保上一步退出时才调用下一步:

mv = spawn 'mv', ['config.json', 'config.json.example']
mv.on 'exit', ->
  npm_publish = spawn 'npm', ['publish']
  npm_publish.on 'exit', ->'
    spawn 'mv', ['config.json.example', 'congfig.json']

这样就可以了。可是每次这么写还蛮烦的。我们把它抽象成一个函数。

嗯,该怎么写呢?首先,我们确定这个函数的输入,函数应当接受一个命令,后面是一串回调函数。因此:

shell_commands = (args...) ->

args...是splats,用来表示参数数目不定。

然后我们需要做的就是执行这个命令,在命令执行完毕之后,运行那一串回调函数。

因此,我们首先得到需要执行的命令,这很简单,pop掉最后的一串回调函数,再交给spawn执行即可。

args.pop()
[command, args...] = args
spawn command, args

注意上面的args...同样是splats,这次用于模式匹配。

然后加上运行回调函数的代码,我们的函数基本就成形了:

shell_commands = (args...) ->
  callback = args.pop()
  [command, args..] = args
  shell_command = spawn command, args
  shell_command.on 'exit' ->
    callback()

有个问题,回调到最后,会是单纯的命令,没有回调函数了。因此我们加一个判断,如果args的最后一项不是函数的话,那就不pop了,直接执行命令就行了:

shell_commands = (args...) ->
  if typeof(args[a.length - 1]) is 'function'
    callback = args.pop()
  else
    callback = ->
  [command, args..] = args
  shell_command = spawn command, args
  shell_command.on 'exit' ->
    callback()

抽象出了这个函数以后,我们原先的代码就可以这么写了:

shell_commands 'mv', 'config.json', 'config.json.example', ->
  shell_commands 'npm', 'publish', ->
    shell_commands 'mv', 'config.json.example', 'config.json'

是不是清爽多了?

没有处理的问题是,万一在重命名的过程中出问题了,那么我们不应该发布NPM包。所以,我们加一下判断,如果进程的exit code不为0(这就意味着有错误),那么继续执行。

shell_commands = (args...) ->
  if typeof(args[a.length - 1]) is 'function'
    callback = args.pop()
  else
    callback = ->
  [command, args..] = args
  shell_command = spawn command, args
  shell_command.on 'exit', (code) ->
    if code isnt 0
      callback(code)
    else
      console.log("Exited with status: " + code)

相应地,调用的时候也需要传入code

shell_commands 'mv', 'config.json', 'config.json.example', (code) ->
  shell_commands 'npm', 'publish', (code) ->
    shell_commands 'mv', 'config.json.example', 'config.json'

通常大家喜欢verbose的输出,那么我们就在终端显示一下执行的命令:

console.log(command, " ", args.join(" "))

最终的CakeFile类似这样:

{spawn} = require 'child_process'

shell_commands = (args...) ->
  if typeof(args[a.length - 1]) is 'function'
    callback = args.pop()
  else
    callback = ->
  [command, args..] = args
  console.log(command, " ", args.join(" "))
  shell_command = spawn command, args
  shell_command.on 'exit', (code) ->
    if code isnt 0
      callback(code)
    else
      console.log("Exited with status: " + code)

task "publish", "publish NPM", ->
  shell_commands 'mv', 'config.json', 'config.json.example', (code) ->
    shell_commands 'npm', 'publish', (code) ->
      shell_commands 'mv', 'config.json.example', 'config.json'

task "test", "run unit tests", ->
  shell_commands './node_module/.bin/mocha'
查看原文

认证与成就

  • 获得 154 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2014-02-21
个人主页被 2k 人浏览