内建对象是指由ECMAScript实现提供的、不依赖于宿主环境的对象,这些对象在程序运行之前就已经存在了。内建对象就好比是JDK中的类库,开发者可以直接拿来使用,这极大的方便了常见的编程任务。这篇文章就来浏览一下主要的内建对象,当然,我们并不是第一次接触内建对象,前面已经接触到的就有Object、Function、Boolean、Number、String,对于已经介绍过的,这里再总结复习一下,没有介绍过的,根据相关性来对比的总结,RegExp对象及正则表达式在下一篇中再单独介绍。
1、内建全局单例对象
(1)内建全局单例对象:在整个执行环境中只有一个对象实例,这些对象没有内部属性[[Construct]]和[[Call]],因此不能使用new来创建,也不能作为函数来调用,而是直接使用对象名称来引用其属性和方法(对于全局对象,则可以直接使用属性和方法名)。内建全局单例对象有Global、Math、JSON。
(2)内建常量:主要是指内建全局单例对象的属性,这些属性的[[Writable]]、[[Configurable]]、[[Enumerable]]特性全部为false,因此不能修改属性值,不能删除属性,也不能在for-in循环中枚举。这些内建常量有:
对象 | 名称 | 常量值 | 说明 | 对象 | 名称 | 常量值 | 说明 |
Global | NaN | NaN | 表示不是数值 | Math | E | ≈2.718 | 自然对数的底数 e |
Infinity | +∞ | 正无穷 | LN10 | ≈2.303 | 2 的自然对数 | ||
undefined | undefined | 未定义 | LN2 | ≈0.693 | 10的自然对数 | ||
LOG2E | ≈1.443 | e 的以2 为底的对数 | |||||
LOG10E | ≈0.434 | e 的以10为底的对数 | |||||
PI | ≈3.142 | 圆周率,即圆周长与直径的比 | |||||
SQRT1_2 | ≈0.707 | 2的平方根的倒数 | |||||
SQRT2 | ≈1.414 | 2的平方根 |
注:Global对象中的常量可以使用名称直接访问,Math对象中的常量需使用类似Math.PI的形式来访问。
(3)内建静态方法:
所属对象 | 类别 | 方法 | 说明 |
Global | 全局解析方法 | eval(x) | 解析Javascript字符串,eval中定义的变量不会提升,在严格模式下,外部不能访问eval内定义的变量 |
字符串解析为Number | parseInt(string,radix) | 将字符串解析为整数,可以传入一个进制,会忽略前导空格 | |
parseFloat(string) | 将字符串解析为浮点数,会忽略前导的空格和前导0 | ||
Number判断方法 | isNaN(number) | 判断是否为数字 | |
isFinite(number) | 判断是否为有限数 | ||
URI处理方法 | encodeURI(uri) | 对URI编码,用于整个URI,用特殊的UTF-8编码替换所有无效字符,不会对本身属于URI的特殊字符编码,如冒号,正斜杠,问号,井号等。 | |
decodeURI(ecodedURI) | 对使用ecnodeURI()编码的字符串解码 | ||
encodeURIComponent(uriComponent) | 对URI编码,用于URI中的某一段,会对发现的任何非标准字符进行解码 | ||
decodeURIComponent(encodedURIComponent) | 对使用ecnodeURIComponent()编码的字符串解码 | ||
内建对象构造器方法 |
Object、Function、Array、String、Number、Boolean、Date、RegExp Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError |
这里每一个构造函数都构成了一个内建的对象类型 | |
Math | 三角函数 | sin(x)、cos(x)、tan(x) | x的正弦、余弦、正切 |
反三角函数 | asin(x)、acos(x)、atan(x)、atan2(y,x) | x的烦正弦、反余弦、反正切、y/x的反正切 | |
舍入函数 | ceil(x)、floor(x)、round(x) | 向上舍入(大于该数的最小整数)、向下舍入(小于该数的最大整数)、四舍五入 | |
最值函数 | max([value1[value2[,...]]])、min([value1[,value2[,...]]]) | 最大值、最小值 | |
随机函数 | random() | 返回介于0和1之间的随机数,不包括0和1.随机公式:随机值=Math.floor(Math.random() * 可能值的个数 + 初始值) | |
其它常见数学函数 | abs(x)、exp(x)、log(x)、pow(x,y)、sqrt(x) | 绝对值、Math.E的x次幂、x的自然对数、x的y次幂、x的平方根 | |
JSON | 解析 | parse(text[,reviver]) | 把JSON字符串解析外为Javascript值 |
序列化 | stringify(value[,replacer[,space]]) | 把Javascript对象序列号为JSON字符串,默认情况下不包括空格和缩进,所有函数、原型成员以及值为undefined的属性会被忽略 |
说明:
(1)全局对象中还有escape()/unescape()方法,由于这两个方法只能正确编码ASCII字符已经被废弃,而使用上表中的encodeURI()等方法来替换。
(2)JSON.parse()可以接受一个可选的参数,这个参数是一个函数,被称为还原函数,还原函数返回一个值,接受两个参数:一个键和一个值。如果还原函数返回undefined,表示要从结果中删除相应的键,返回其他值,则将该值插入到结果中。
(3)JSON.stringify()可以接受二个可选参数:
A、第一个可选参数是个过滤器,可以是一个数组,也可以是一个函数。如果是一个数组,那么结果中只保留这个数组中列出的属性;如果是一个函数,这个函数被称为替换函数,接受两个参数:一个键和一个值。替换函数返回undefined时会忽略这个键,否则就将返回值作为这个键的值插入到相应位置。
B、第二个可选参数是个选项,表示是否在JSON字符串中保留缩进。如果这个参数是数字,表示每个级别缩进的空格数(最大不能超过10,超过10时自动设置为10),如果这个参数是字符串,则将作为缩进字符处理。
在调用JSON.stringify(obj)时,如果obj中有toJSON()方法并返回一个有效值时,会首先调用这个方法。
2、Object与Function
这两个内建对象在前面已经重点讨论过,这里总结一下:
对象/构造函数/[[Class]] | 构造器属性(静态属性) | 原型属性 | 实例属性 | 内部属性 |
Object | prototype | constructor | [[Prototype]] | |
defineProperty() | toString() | [[Class]] | ||
defineProperties() | toLocaleString() | [[Extensible]] | ||
getOwnPropertyDescriptor() | valueOf() | [[Get]] | ||
preventExtensions() | hasOwnProperty() | [[GetOwnProperty]] | ||
seal() | propertyIsEnumerable() | [[GetProperty]] | ||
isSeal() | isPrototypeOf() | [[Put]] | ||
frozen() | [[CanPut]] | |||
isFreeze() | [[HasProperty]] | |||
create() | [[Delete]] | |||
getOwnPropertyNames() | [[DefaultValue]] | |||
getPrototypeOf() | [[DefineOwnProperty]] | |||
keys() | ||||
Function | prototype | call() | prototype | [[HasInstance]] |
length | apply() | length | [[Scope]] | |
bind() | [[FormalParameters]] | |||
[[Code]] | ||||
[[Construct]] | ||||
[[Call]] |
说明:
(1)构造器属性(静态属性)是直接定义在构造函数这个对象本身上的属性,只能通过构造函数名来直接访问,原型属性是定义在构造函数原型对象上的属性,可以通过原型去访问,但更重要的是可以通过构造函数的实例去访问。比如上表Object对象的defineProperty()就只能以Object.defineProperty()的形式来调用,而hasOwnProperty()这可以在任意一个Object实例对象上调用。
(2)Object本身是一个(构造)函数,也就是Function类的一个实例,因此也就有了Function实例所具有的属性prototype和length(===1,上表未列出),同时,由于Object还是一个构造函数,也就构成了一种(内建)类型Object,通过原型继承,这个类型是ES中所有其它类型的基类,也就是说所有的对象都可以访问上表中Object的原型属性。这里原型继承是基于下面原理来实现的:Object原型的原型是null(即有Object.getPrototypeOf(Object.prototype)===null),其它对象的原型是Object的实例。
(3)Function是一个构造函数,因此构成了一种内建类型Function,同时,因为是函数,也就是一个对象,这个对象的原型对象是Object的一个实例,因而可以访问Object的原型属性(Function类中有些方法覆盖了Object中的原型方法,上表未列出)。
(4)注意区分Function类中的构造器属性和实例属性,可以这样来理解:首先Function类的所有实例都有属性prototype(函数原型对象)和length(形式参数的个数),然后因为Function本身也是一个函数,是Function类的一个实例,因此有prototype和length属性(属性值已经确定了),而这属性是直接定义在Function构造函数上的,也就是构造器属性了。
(5)其它关于Object和Function中不理解的地方可以参考前面的文章,也可以自己查阅相关资料。
3、Array与String
将Array和String这两种内置对象放在一起,主要是因为他们有一些方法比较类似,我自己就常常有搞不拎清的时候,于是借这个机会比较一下。
功能类似方法 | Array对象独有方法 | String对象独有方法 | ||||||||
类别 | Array方法 | String方法 | 类别 | 方法 | 说明 | 类别 | 方法 | 说明 | ||
方法 | 说明 | 方法 | 说明 | |||||||
共有属性 | length | 数组项的个数,可以修改长度来实现添加或移除数组项的功能 | length | 字符串中字符的个数 | 栈和队列 | pop() | 移除数组最后一项,修改数组长度,返回被移除的项 | 去空格 | trim() | 去掉字符串前后的空格 |
对象创建 | 构造函数 |
1、new Array([item0[,item1[,...]]]) 2、new Array(len) 上面两种方式的new可以省略 |
构造函数 |
new String([value]) 注意:上面的new省略时,则作为类型转换函数调用 |
push() | 接受任意个参数,把它们逐个添加到数组末尾,并返回修改后数组的长度 | 比较 | localeCompare() |
对象在参数前返回负数 相等返回0 后面返回正数 |
|
数组字面量 | 使用方括号[] | 字符串字面量 | 使用成对的单引号或成对的双引号 | shift() | 移除数组第一项并返回,修改数组长度 | HTML方法 | 见附表 | 用于简化常见HTML格式化任务的方法,已经不建议使用 | ||
转换方法 | toLocaleString() | 调用数组每一项的toLocaleString(),然后用逗号连接起来 | toLocaleString() | 返回对象表示的字符串 | unshift() | 接受任意个参数,并添加到数组前面,返回新数组的长度 | 大小写转换 | toLowerCase() | 转小写 | |
toString() | 调用数组每一项的toString(),然后用逗号连接起来 | toString() | 返回对象表示的字符串 | 排序 | reverse() | 反转数组项的顺序 | toLocaleLowerCase() | |||
valueOf() | 返回数组本身,即有array === array.valueOf() | valueOf() | 返回对象表示的字符串 | sort() | 默认按升序排序,可以接受一个比较函数 | toUpperCase() | 转大写 | |||
连接方法 | join() | 传入一个参数作为分隔符,将数组每一项连接起来,默认为逗号 | + | 字符串相加 |
迭代方法 两个参数: 1、执行函数(数组项的值,该项在数组中的位置,数组) 2、作用域 |
every() | 对数组中每一项运行执行函数,每一项都返回true时返回true | toLocaleUpperCase() | ||
concat() | 创建一个原数组的副本,将传入的参数压入新数组并返回新数组 | concat() | 拼接字符串,更多情况是直接使用“+”拼接 | some() | 对数组中每一项运行执行函数,如果有其中一项执行函数返回true就返回true | 字符方法 | charAt() |
1个参数:基于0的字符位置 charAt()返回单字符字符串,charCodeAt()返回字符编码 |
||
截取方法 | slice() |
接受1至2个参数,即要返回项的起始和结束位置 1、只有一个参数时,返回该参数位置开始到末尾的所有项 2、参数为负数时,加上数组长度使其变为正数 |
slice() | 参数:开始位置,最后一个字符后面的位置 | forEach() | 对数组中每一项运行执行函数,没有返回值 | charCodeAt() | |||
splice |
第1个参数:要删除的起始项位置;第2个参数:要删除的项数;第3个及之后的参数:要插入的项 1、删除:指定2个参数,要删除的第一项的位置和要删除的项数 2、插入:提供3个参数,起始位置,0,要插入的项 3、替换:提供3个参数,起始位置,删除的项数,要插入的项 |
substr() | 参数:开始位置,字符个数 | map() | 对数组中每一项运行执行函数,返回每次调用的结果组成的数组 | fromCharCode() | 这是String对象的静态函数,将接受到的一或多个字符编码转变为字符串 | |||
substring() | 参数:开始位置,最后一个字符后面的位置 |
filter() |
对数组中的每一项运行执行函数,返回执行函数返回true的项组成的数组 | 模式匹配方法 | match() | 与RegExp的exec()方法相同,接受一个参数,要么是一个正则表达式,要么是一个RegExp对象 | ||||
位置方法 | indexOf() |
接受两个参数:要查找的项和(可选)表示查找起点位置的索引,indexOf()从数组的开头向后查找,lastIndexOf()则从数组末尾向前查找 |
indexOf() |
从字符串中查找子字符串,返回子字符串的位置,没有找到返回-1,indexOf()从前往后查找,lastIndexOf()从后往前找 第二个可选参数表示从哪个位置开始搜索 |
缩小方法 | reduce() |
接受两个参数: 1、执行函数(前一个值,当前值,项的索引,数组),这个函数的返回值会作为第一个参数自动传入下一项,第一次迭代发生在数组的第二项上 2、(可选)初始值 reduce()从数组第一项开始,遍历至最后,reduceRight()从数组最后一项开始,遍历至第一项 |
search() | 接受一个参数,和match()相同,返回字符串中第一个匹配项的索引,没有找到匹配项时返回-1,search()始终从字符串开头向后查找 | |
lastIndexOf() | lastIndexOf() | reduceRight() | replace() | 接受两个参数:一个RegExp对象或字符串和一个字符串或函数,若第一个参数为字符串,则只会替换第一个字符串,若想替换所有子字符串,第一个参数必须为指定了全局标志(g)的正则表达式 | ||||||
判断方法 | isArray() | 静态方法,接受一个参数,返回这个参数是否为Array | split() |
基于指定的分隔符将一个字符串分割成多个字符串,并将结果放在一个数组中返回,分隔符可以是字符串,也可以是正则表达式。可选的第二个参数用于指定数组的最大长度 |
说明:
(1)上表中红色部分表示在ES5版本中新增的方法,蓝色部分为个人认为比较常用的属性和方法。
(2)ECMAScript中数组的每一项可以保存任意类型的数据,并且数组的大小可以随着数据的添加而自动的动态调整。
(3)使用Array构造函数创建数组时,如果传入一个数值类型的参数,则作为数组长度处理,如果这个数值小于0或者不是一个整数,会抛出RangeError异常(如果确实需要将这个数值作为数组第1项,可以使用数组字面量),其它数值类型的参数,则作为数组的第一项值处理,并且数值的长度值为1。
try{ var a = new Array(-2); }catch(e) { console.info(e);//RangeError } //var g = new Array(1.1);异常 var b = new Array(0); var c = new Array(2); var d = new Array('data'); var e = [-2]; var f = new Array(-1,-2); console.info(b.length);//0 console.info(c.length);//2 console.info(d.length);//1 console.info(e.length);//1 console.info(f.length);//2
(4)判断一个对象是否为数组时,在ES5中可以直接使用Array.isArray(obj), 在不支持isArray方法的环境中时,可以使用obj instanceof Array来判断只有一个作用域的情况,但是更加稳妥的判断方法是利用Array对象的内部属性[[Class]]来判断:
function isArray(obj){ return Object.prototype.toString.call(obj) == '[object Array]'; }
(5)关于String的slice()、sbustr()、substring(),如果只传入了第一个参数,则截取从第一个参数至末尾。当传入负参数时:
A、slice()会将负参数加上字符串长度,使参数为正
B、substr()会将负的第一个参数加上字符串的长度,将负的第二个参数转换为0
C、substring()会将所有负参数转换为0,如果第2个参数小于第1个参数,会互换两个参数
(6)关于String对象replace()方法的第二个参数
如果是字符串,可以使用一些特殊字符将正则表达式操作得到的值插入到结果字符串中,这些特殊字符有:
字符序列 | 替换文本 |
$$ | $ |
$& | 匹配整个模式的字符串,与RegExp.lastMatch的值相同 |
$' | 匹配的子字符串之前的子字符串,与RegExp.leftContext的值相同 |
$` | 匹配的子字符串之后的子字符串,与RegExp.rightContext的值相同 |
$n | 匹配第n个捕获组的子字符串,其中n等于1~9,如果正则表达式中没有定义捕获组,则使用空字符串 |
$nn | 匹配第nn个捕获组的子字符串,其中n等于01~99,如果正则表达式中没有定义捕获组,则使用空字符串 |
如果是函数,这个函数接受的参数:模式的匹配项,第一个捕获组的匹配项,...,第n个捕获组的匹配项,模式的匹配项在字符串中的位置,原始字符串。函数应该返回一个字符串,表示应该被替换的匹配项。
(7)String对象的HTML方法
方法 | 输出结果 | 方法 | 输出结果 |
anchor(name) | <a name="name">string</a> | italics() | <i>string</i> |
big() | <big>string</big> | link(url) | <a href="url">url</a> |
bold() | <b>string</b> | small() | <small>string</small> |
fixed() | <tt>string</tt> | strike() | <strike>string</strike> |
fontcolor(color) | <font color="color">string</font> | sub() | <sub>string</sub> |
fontsize(size) | <font size="size">string</font> | sup() | <sup>string</sup> |
4、Number与Boolean
String、Number和Boolean对象是相应简单数据类型的包装对象,他们都有一个共同的特征:作为构造函数调用时是创建一个对象,作为一般函数调用时则是类型转换。由于所有对象相应的Boolean类型值都是true,所以需要特别注意的是new Boolean(false)在布尔运算中会作为true去处理,这里的建议就是永远不要使用Boolean对象。
var falseValue = false; var falseObject = new Boolean(false); console.info(typeof falseValue);//boolean console.info(typeof falseObject);//object console.info(falseValue instanceof Boolean);//false console.info(falseObject instanceof Boolean);//true console.info(falseValue && true);//false console.info(falseObject && true);//true
String、Number和Boolean类型的变量可以直接调用相应包装对象的方法,实际上在后台会自动转换为相应包装对象,然后调用方法。String和Boolean类型的字面量也可以直接调用包装对象的方法,但是Number类型的字面量不能直接调用Number对象的方法。
var num = 10; console.info(num.toFixed(2));//10.00 //console.info(10.toFixed(2));//异常 console.info(false.toString());//false console.info('abcdefg'.substr(3));//defg
关于包装对象的属性和方法,String对象已经在上一小节列出,Boolean对象除覆盖了Object的toString()和valueOf()外没什么特别需要注意的,下面再总结一下Number对象的属性和方法。
静态属性(常量) | 说明 | 方法 | 说明 |
Number.MAX_VALUE | Number类型能够表示的最大值 | valueOf() | 返回对象表示的基本类型的数值 |
Number.MIN_VALUE | Number类型能够表示的最小值 | toLocaleString() | 返回对象表示的数值的字符串形式 |
Number.NaN | NaN | toString() | 返回对象表示的数值的字符串形式,可以接受一个表示进制的参数 |
Number.NEGAIVE_INFINITY | 负无穷 | toFixed() | 按照指定的小数位返回数值的字符串表示,如果数值比指定的小数位多,会进行四舍五入处理 |
Number.POSITIVE_INFINITY | 正无穷 | toExponential() | 返回以指数表示法表示的数值的字符串形式,接受一个表示小数个数的参数 |
toPrecision() | 接受一个表示数值的所有数字的位数(不包括指数部分),可能返回固定大小格式,也可能返回指数形式 |
5、Date
ECMAScript中的Date对象和Java中的java.util.Date一样,采用UTC(Coordinated Universal Time,国际协调时间)1970年1月1日午夜(零时)开始经过的毫秒数来保存日期。
(1)创建日期对象
A、构造函数:可以通过new Date()创建对象自动获取当前日期和时间,也可以传入表示日期的毫秒数来创建日期,还可以传入和下面的Date.parse()与Date.UTC()相同的参数(在后台会先调用Date.parse()或Date.UTC(),后台调用Date.UTC()时是基于系统本地时区而非GMT创建的)来创建日期。
B、Date.parse():接受一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数。日期格式和具体的实现及地区有关。如果传入的字符串不能表示日期,返回NaN。
C、Date.UTC():返回表示日期的毫秒数,参数分别是年份、基于0的月份、月中的哪一天(1~31)、小时(0~23)、分钟、秒以及毫秒数,这些参数中,前面两个参数(年月)是必须的,没有提供天数时默认为1,其它参数没有提供时默认为0。
D、Date.now():在ES5中新增,返回表示调用这个方法的日期和时间的毫秒数。这可以用来分析代码执行的时间:
//支持Date.now()时 //不支持Date.now()的情况下 var start = Date.now(); var start = +new Date(); //doSomething(); //doSomething(); var end = Date.now(); var end = +new Date(); var time = end -start; var time = end - start;
(2)方法列表
方法 | 说明 | getter/setter方法 | 说明 |
toLocaleString() | 按照与浏览器设置的地区相适应的格式返回日期和时间,其中时间一般以12小时制表示(通常含AM或PM) | setTime(毫秒) | 没有对应的UTC方法 |
toString() | 通常返回带有时区信息的日期和时间,其中时间一般以24小时制表示 | setFullYear(年) | 4位数的年份 |
valueOf() | 返回日期的毫秒表示,这为日期的比较提供了便利 | setMonth(月) | 0~11,0表示一月,11表示十二月,超过11增加年份 |
toDateString() | 以特定于实现的格式显示星期几、月、日和年 | setDate(日) | 超过范围时会增加月份 |
toTimeString() | 以特定于实现的格式显示时、分、秒和时区 | setHours(时) | 传入值超过了23会增加天数 |
toLocaleDateString() | 以特定于实现的格式显示星期几、月、日和年 | setMinutes(分) | 传入值超过了59会增加小时数 |
toLocaleTimeString() | 以特定于实现的格式显示时、分、秒 | setSeconds(秒) | 传入值超过了59会增加分钟数 |
toUTCString() | 以特定于实现的格式显示完整的UTC日期 | setMilliseconds(毫秒) | |
toGMTString() | 和toUTCString()等价,主要是为了向后兼容而保留的 | getDay() | 没有对应的setter方法,0表示星期日,6为星期六 |
getTimezoneOfSet() | 返回本地时间与UTC时间相差的毫秒数 |
说明:上表getter/setter列中,除了setTime()外,均有一套相应UTC方法,比如对应setFullYear()有getFullYear()、setUTCFullYear()、getUTCFullYear()方法。
6、Error
(1)从ES3开始引入了try-catch语句,用于捕获异常,结构和Java中的异常处理类似。这里需要注意的是,在使用finally子句时,如果里面有return语句,由于finally语句无论怎样都会执行,因此会覆盖之前的return语句。
function testFinally(){ try{ return 2; }catch(error){ return 1; }finally{ return 0; } } console.info(testFinally());//0
说明:按照规范,catch和finally子句只要有一个即可,但是在IE7的实现中有一个bug,没有catch子句时就不会执行finally子句,所以为了保证兼容性,每一个try都加上catch子句(如果需要在外层处理,可以把捕获的异常使用throw向外抛出)。
(2)错误类型
错误类型 | 说明 |
Error | Error是所有错误类型的父类,因此所有错误类型共享了一组相同的属性和方法,这个基类型的主要作用是供开发人员抛出自定义错误 |
EvalError | 在使用eval()函数而发生异常时抛出,简单的说,如果没有把eval()当成函数调用,就会抛出错误 |
RangeError | 在数值超出范围时抛出,如定义数组时传入负参数就会抛出RangeError |
ReferenceError | 找不到对象的情况下抛出 |
SyntaxError | 把语法错误的字符串传入eval()时抛出 |
TypeError | 在变量中保存着意外的类型,或者访问不存在的方法时,会导致这种错误 |
URIError | 在使用encodeURI()或decodeURI(),URI格式不正确时抛出 |
注:这里只是简要列举了一些内建的错误对象,没有对错误处理以及调试技术做过多的阐述,感兴趣的朋友可以自行查找相关资料。