JavaScript摘要
1.基本数据类型
JavaScript的基本构建块包括:对象(object)、原语(primitive)和字面量(literal)。
literal 表示特定类型的一个值,例如:String, Number, or Boolean。
1 | "this is a string" |
Primitive 是一个特定数据类型的实例,包括五种:String, Number, Boolean, null, undefined。
JavaScript 的世界中,一切皆对象(object)。
2.基本语法
函数声明:
1 | function distance(x1, y1, x2, y2) { |
条件语句:
1 | if (x <= 1){ |
循环语句:
1 | for(i=0;i<10;i++){ |
3.数组
创建数组:
1 | var arr = new Array(element0, element1, ..., elementN); |
填充数组:
1 | var emp = []; |
如果你在以上代码中给数组操作符的是一个非整形数值,那么将作为一个代表数组的对象的属性(property)创建,而非作为数组的元素。
引用数组元素:
1 | var arr = ["one", "two", "three"]; |
数组操作符(方括号 [ ])也可以用来访问数组的属性(在 JavaScript 中,数组也是对象)。
遍历数组:
1 | var colors = ['red', 'green', 'blue']; |
数组对象的方法:
concat()
连接两个数组并返回一个新的数组。
join(deliminator = ',')
将数组的所有元素连接成一个字符串。
push()
在数组末尾添加一个或多个元素,并返回数组操作后的长度。
pop()
从数组移出最后一个元素,并返回该元素。
shift()
从数组移出第一个元素,并返回该元素。
4.集合类
Map
1 | var sayings = new Map(); |
Map和Object的比较:
一般地,objects会被用于将字符串类型映射到数值。Object
允许设置键值对、根据键获取值、删除键、检测某个键是否存在。而Map
具有更多的优势。
Object
的键均为Strings
类型,在Map
里键可以是任意类型。- 必须手动计算
Object
的尺寸,但是可以很容易地获取使用Map
的尺寸。 Map
的遍历遵循元素的插入顺序。Object
有原型,所以映射中有一些缺省的键。(可以理解为map = Object.create(null)
)。
Set
1 | var mySet = new Set(); |
Array和Set的对比:
一般情况下,在JavaScript中使用数组来存储一组元素,而新的集合对象有这些优势:
- 数组中用于判断元素是否存在的
indexOf
函数效率低下。 Set
对象允许根据值删除元素,而数组中必须使用基于下标的 splice 方法。- 数组的
indexOf
方法无法找到NaN
值。 Set
对象存储不重复的值,所以不需要手动处理包含重复值的情况。
5.字符串
String 字面量
1 | 'foo' |
String对象
String对象是对 String 类型的封装。
1 | var s = new String("foo"); // Creates a String object |
模板字符串
1 | var a = 5; |
方法 | 描述 |
---|---|
charAt , charCodeAt , codePointAt |
返回字符串指定位置的字符或者字符编码。 |
indexOf , lastIndexOf |
分别返回字符串中指定子串的位置或最后位置。 |
startsWith , endsWith , includes |
返回字符串是否以指定字符串开始、结束或包含指定字符串。 |
concat |
连接两个字符串并返回新的字符串。 |
fromCharCode , fromCodePoint |
从指定的Unicode值序列构造一个字符串。这是一个String类方法,不是实例方法。 |
split |
通过将字符串分离成一个个子串来把一个String对象分裂到一个字符串数组中。 |
slice |
从一个字符串提取片段并作为新字符串返回。 |
substring , substr |
分别通过指定起始和结束位置,起始位置和长度来返回字符串的指定子集。 |
6.面向对象
基于类VS基于原型的语言
基于类的面向对象语言,比如 Java 和 C++,是构建在两个不同实体的概念之上的:即类和实例。
- 类可以定义属性,这些属性可使特定的对象集合特征化(可以将 Java 中的方法和变量以及 C++ 中的成员都视作属性)。类是抽象的,而不是其所描述的对象集合中的任何特定的个体。例如
Employee
类可以用来表示所有雇员的集合。 - 另一方面,一个实例是一个类的实例化;也就是其中一名成员。例如,
Victoria
可以是Employee
类的一个实例,表示一个特定的雇员个体。实例具有和其父类完全一致的属性。
基于原型的语言(如 JavaScript)并不存在这种区别:它只有对象。基于原型的语言具有所谓原型对象的概念。原型对象可以作为一个模板,新对象可以从中获得原始的属性。任何对象都可以指定其自身的属性,既可以是创建时也可以在运行时创建。而且,任何对象都可以作为另一个对象的原型,从而允许后者共享前者的属性。
差异总结
基于类的(Java) | 基于原型的(JavaScript) |
---|---|
类和实例是不同的事物。 | 所有对象均为实例。 |
通过类定义来定义类;通过构造器方法来实例化类。 | 通过构造器函数来定义和创建一组对象。 |
通过 new 操作符创建单个对象。 |
相同。 |
通过类定义来定义现存类的子类,从而构建对象的层级结构。 | 指定一个对象作为原型并且与构造函数一起构建对象的层级结构 |
遵循类链继承属性。 | 遵循原型链继承属性。 |
类定义指定类的所有实例的所有属性。无法在运行时动态添加属性。 | 构造器函数或原型指定初始的属性集。允许动态地向单个的对象或者整个对象集中添加或移除属性。 |
- 首先了解该语言的基本数据类型,基本语法和主要语言构造,主要数学运算符和print函数的使用,达到能够写谭浩强程序设计书课后数学习题的程度;
- 其次掌握数组和其他集合类的使用,有基础的话可以理解一下泛型,如果理解不了也问题不大,后面可以补;
- 简单字符串处理。所谓简单,就是Regex和Parser以下的内容,什么查找替换,截断去字串之类的。不过这个阶段有一个难点,就是字符编码问题。如果理解不了,可以先跳过,否则的话最好在这时候把这个问题搞定,免留后患;
- 基本面向对象或者函数式编程的特征,无非是什么继承、多态、Lambda函数之类的,如果有经验的话很快就明白了;
- 异常、错误处理、断言、日志和调试支持,对单元测试的支持。你不一定要用TDD,但是在这个时候应该掌握在这个语言里做TDD的基本技能;
- 程序代码和可执行代码的组织机制,运行时模块加载、符号查找机制,这是初学时的一个难点,因为大部分书都不太注意介绍这个极为重要的内容;
- 基本输入输出和文件处理,输入输出流类的组织,这通常是比较繁琐的一部分,可以提纲挈领学一下,搞清楚概念,用到的时候查就是了。到这个阶段可以写大部分控制台应用了;
- 该语言如何进行callback方法调用,如何支持事件驱动编程模型。在现代编程环境下,这个问题是涉及开发思想的一个核心问题,几乎每种语言在这里都会用足功夫,.NET的delegate,Java的anonymous inner class,Java 7的closure,C++OX的 tr1::function/bind,五花八门。如果能彻底理解这个问题,不但程序就不至于写得太走样,而且对该语言的设计思路也能有比较好的认识;
- 如果有必要,可在这时研究regex和XML处理问题,如无必要可跳过;
- 序列化和反序列化,掌握一下缺省的机制就可以了;
- 如果必要,可了解一下线程、并发和异步调用机制,主要是为了读懂别人的代码,如果自己要写这类代码,必须专门花时间严肃认真系统地学习,严禁半桶水上阵;
- 动态编程,反射和元数据编程,数据和程序之间的相互转化机制,运行时编译和执行的机制,有抱负的开发者在这块可以多下些功夫,能够使你对语言的认识高出一个层面;
- 如果有必要,可研究一下该语言对于泛型的支持,不必花太多时间,只要能使用现成的泛型集合和泛型函数就可以了,可在以后闲暇时抽时间系统学习。需要注意的是,泛型技术跟多线程技术一样,用不好就成为万恶之源,必须系统学习,谨慎使用,否则不如不学不用;
- 如果还有时间,最好咨询一下有经验的人,看看这个语言较常用的特色features是什么,如果之前没学过,应当补一下。比如Ruby的block interator, Java的dynamic proxy,C# 3的LINQ和extension method。没时间的话,我认为也可以边做边学,没有大问题。
- 有必要的话,在工作的闲暇时间,可以着重考察两个问题,第一,这个语言有哪些惯用法和模式,第二,这个语言的编译/解释执行机制。