面向对象的程序设计
5.1 Object类型
创建对象
方式一:new
操作符+构造函数
方式二:对象字面量表示法
var person = {
name : "Ethan",
age : 22
};
访问对象的属性:点表示法和方括号表示法
5.2 Array类型
创建数组
方式一:new Array();
或者 Array()
; new
操作符可以省略。
方式二:数组字面量 [ ]
数组的length
属性不是只读的,可以修改。修改后数组长度变短的话,则删除数组末尾多出来的元素;数组长度变长的话,则在数组末尾增加新的元素,元素的值为undefined
。
检测数组:instanceof
和Array.isArray()
栈方法:push()
pop()
两个方法都是操作数组末端
队列方法:push()
方法向数组末端添加元素
shift()
方法在数组前端移除一个元素并返回这个元素
unshift()
方法和shift()
方法功能相反,在数组前端添加一个元素并返回数组的长度
重排序方法:**reverse()
和sort()
这两个方法都会对调用的数组执行操作,不会生成新的数组**。
reverse()
:反转数组项的顺序
sort()
:默认是升序(从小到大排列),但是默认的sort()
方法并不好用,因为它比较的是字符串的大小,进行比较时,调用数组中每个元素的toString()
方法,转换成字符串再进行比较。为了防止这个弊端,需要向sort()
方法中传入一个比较函数,比较函数由自己定义。传入方法名即可。
function compare(value1,value2) {
return value2-value1
}
var array = [0,10,2,4,5];
array.sort(compare);
alert(array);
上面的示例是升序排列,若要降序排列,compare()
方法中return value1-value2即可。
操作方法
contact()
连接多个数组并生成一个新的数组,不影响新的数组
slice()
基于当前的数组中的一个或多个项创建新的数组,不影响新的数组。考虑slice()
方法中参数是负数的情况。
splice()
执行删除、插入和替换操作(传入的参数不同)
位置方法
indexOf()
lastIndexOf()
两个方法分别从前向后和从后向前查,都返回查到的参数在数组中的位置,找不到则返回-1。这两个方法在查找时执行的是全等(===),不会进行类型转换。
迭代方法
evevy()
filter()
forEach()
map()
some()
参数是一个函数,对数组中的每一个元素执行函数,区别是返回值不同。
缩小方法
reduce()
和 reduceRight()
方法,不是很理解什么叫数组缩小方法。
5.3 Date类型
继承的方法
valueOf()
方法返回的是当前日期的毫秒表示。
日期格式化方法
日期/时间组件方法
基本上就是一些getTime()
之类的方法,用到的时候可以细查API
5.4 RegExp类型
正则表达式:pattern+flag
其中,pattern模式指的是任意的正则表达式;flag则是标明正则表达式的行为,有g、i、m三个flag,分别代表了global
(全局)、case-insensitive
(忽略大小写)和multiline
(多行匹配)。
创建正则表达式的两种方式:字面量方式和RegExp构造函数。使用这两种方式构造的字符串是不一样的,使用字面量方式创建的正则表达式会共用一个RegExp实例,而使用RegExp构造函数创建的每一个正则表达式都是一个新实例。在使用正则表达式时,最好每次都创建一个新实例。
RegExp的实例属性:global
、ignoreCase
、lastIndex
(开始搜索下一个匹配项的字符位置,从0开始)、multiline
、source
(正则表达式字符串)
RegExp的实例方法:主要是exec()
方法
RegExp构造函数属性:input
、lastMatch
、lastParen
、lastContext
、multiline
、rightContext
注意:Opera和IE浏览器不支持一些属性
5.5 Function类型
由于函数也是一个对象,因此函数名就是一个指向函数对象的指针。
创建函数最好不要使用Function构造函数创建,会带来性能上的问题。
没有重载(深入理解)
创建同名函数时,后面函数的函数名实际上覆盖了前面同名函数的函数名。
函数声明与函数表达式
最好使用函数声明而非函数表达式。原因是解析器的函数声明提升过程,会将函数声明提升到源代码树的顶部,而使用函数表达式声明的函数是作为一个变量的初始化语句,不执行到对应的函数表达式声明语句,在这之前使用这个函数都是空引用,会出现“unexpected
identifier”(意外标识符)错误。
作为值的函数
从一个函数中返回另一个函数:
function dad_function() {
return function () {
some code by son_function……
}
}
函数内部属性:arguments
和this
arguments
的callee
属性:这个属性是一个指针,指向拥有这个arguments
类数组对象的函数,这个属性用来松耦合。看以下书中的例子,一个经典的阶乘函数:
function factorial(num) {
if(num<=1) {
retrurn 1;
} else {
return arguments.callee(num-1);
}
}
一个典型的递归求阶乘的算法,这里使用arguments.callee
代替了函数名factorial
,说明arguments.callee
就是一个函数对象的指针。
this
属性:和Java与C#中的this
相类似,this
指的是函数执行的环境对象(例如一个全局函数的this
就是window
)
函数的名字仅仅是一个包含指针的变量而已。
caller
属性:保存了调用当前函数的函数的应用。
function outer() {
inner();
}
function inner() {
alert(inner.caller);
}
outer(); //警告框显示outer函数的代码
为了松耦合,可以这样写:
function outer() {
inner();
}
function inner() {
alert(arguments.callee.caller);
}
outer(); //警告框显示outer函数的代码
严格模式下,不能为函数的caller
属性赋值。
严格模式下限制颇多,ECMAScript5还定义了一个arguments.caller
属性,为了区分函数的caller
属性,加强安全性,使用严格模式访问这两个属性会报错。
函数属性和方法
每个函数都有的两个属性:length
和prototype
。length
属性表示函数希望接收的命名参数的个数(即函数定义时的参数个数);prototype
中的属性不可枚举,因此使用for-in也不能遍历它的属性。
每个函数都有两个非继承来的方法:apply
和call
这两个方法功能是一致的:apply
方法接收两个参数,第一个参数是函数的执行环境(一般是this
),另一个是执行函数所需的参数(可以传入arguments
或者一个Array数组);而call
方法第一个参数和apply
方法相同,第二个参数却需要把所需参数一个一个都列举出来,不能使用arguments
和Array数组。
实际上,apply
和call
方法并非为了传递参数,其真正的功能在于可以改变函数执行的环境,即能够扩充函数赖以运行的作用域。看下面一个例子:
window.color = "red";
var o = {color:"blue"};
function sayColor() {
alert(this.color);
}
sayColor(); //全局环境下运行,this就是window,弹出“red”
sayColor.call(this); //"red"
sayColor.call(window); //"red"
sayColor.call(o); //"blue"
使用call
和applly
两个方法的最大好处,就是对象和方法不必再有紧耦合的关系。
函数还有一个bind()
方法,关于这个方法的功能,在第22章 高级技巧 有参考。
这个函数会创建一个函数实例,其this
值会被绑定到传给bind()
函数的值。
5.6 基本包装类型
三个基本数据类型对应的特殊引用类型:Number
、Boolean
和String
自动装箱和拆箱过程在后台执行时会新建一个基本类型的对应包装类型的实例,但是这个实例只存在一行代码的一瞬间,并非常驻内存,如果要使用对应的包装类型,直接使用new
操作符+对应的包装类型即可。
转型函数和包装类型构造函数的不同
var value = "25";
var number = Number(value); //转型函数
alert(typeof number); //"number"
var obj = new Number(value);
alert(typeof obj); //"object"
Boolean类型
最好永远不要使用Boolean对象,而是使用boolean基本类型。
因为布尔运算(逻辑运算)中,所有的对象都会被转换为true
:
var falseObect = new Boolean(false);
var result = falseObject && true;
alert(result); //true
示例中的falseObject是一个对象,在布尔运算中被转换为true
,所以result为true
。
Number类型
主要是一些格式化数值的方法:toFixed()
toExponential()
toPrecision()
String类型
字符方法、字符串操作方法、字符串位置方法、trim()
方法、字符串大小写转换方法、字符串模式匹配方法、localeCompare()
方法、fromCharCode()
方法、HTML方法
5.7 单体内置对象
Global对象:URI编码方法、eval()
方法
重点是eval()
方法:将内容解释为JavaScript代码。
注意:eval()
方法中所定义的变量和函数都不会进行提升,只能在执行到eval()方法时创建。
使用eval()
方法必须要谨慎,防止代码注入。
在JavaScript中,Global对象被定义为window
对象的一部分。
Math对象
主要是Math
对象的一些常用的方法,用的话查API。