JavaScript 的所有其他对象都继承自Object
对象,即那些对象都是Object
的实例。
Object
对象的原生方法分成两类:Object
本身的方法:直接定义在Object对象的方法Object
的实例方法:定义在Object原型对象Object.prototype上的方法Object
本身是一个函数,可以当作工具方法使用,将任意值转为对象。Object
构造函数的首要用途,是直接通过它来生成新对象。💡 虽然用法相似,但是Object(value)
与new Object(value)
两者的语义是不同的,Object(value)
表示将value
转成一个对象,new Object(value)
则表示新生成一个对象,它的值是value
。
Object.keys
方法(只返回可枚举的属性,更常用)和Object.getOwnPropertyNames
方法都用来遍历对象的属性。Object.prototype.valueOf()
:返回当前对象对应的值。JavaScript 自动类型转换时会默认调用这个方法,可以用自定义的obj.valueOf覆盖Object.prototype.valueOfObject.prototype.toString()
:返回当前对象对应的字符串形式。数组、字符串、函数、Date 对象都分别部署了自定义的toString
方法,覆盖了Object.prototype.toString
方法。Object.prototype.toLocaleString()
:返回当前对象对应的本地字符串形式。Object.prototype.hasOwnProperty()
:判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。Object.prototype.isPrototypeOf()
:判断当前对象是否为另一个对象的原型。Object.prototype.propertyIsEnumerable()
:判断某个属性是否可枚举。JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。
{
value: undefined,
writable: true,
enumerable: true, //是否可遍历
configurable: true, //是否可配置
get: undefined,
set: undefined
}
💡 一旦定义了取值函数get
(或存值函数set
),就不能将writable
属性设为true
,或者同时定义value
属性,否则会报错。
Object.getOwnPropertyDescriptor() | - 获取属性描述对象。- 第一个参数是目标对象,第二个参数是一个字符串,对应目标对象的某个属性名。- 只能用于对象自身的属性,不能用于继承的属性。 |
---|---|
Object.getOwnPropertyNames() | 返回一个数组,成员是参数对象自身的全部属性的属性名,不管该属性是否可遍历。 |
Object.defineProperty(),Object.defineProperties() | - 通过属性描述对象,定义或修改一个属性,然后返回修改后的对象 |
属性描述对象的各个属性称为“元属性”。
value | - 目标属性的值- 只要writable和configurable有一个为true,就允许改动value |
---|---|
writable | - 布尔值,决定了目标属性的值是否可以被改变- 如果原型对象的某个属性的writable为false,那么子对象将无法自定义这个属性。【除非覆盖属性描述对象忽视原型链】 |
enumerable | - 表示目标属性是否可遍历 |
configurable | - 决定了是否可以修改属性描述对象 |
有时需要冻结对象的读写状态,防止对象被改变。JavaScript 提供了三种冻结方法,最弱的一种是Object.preventExtensions
,其次是Object.seal
,最强的是Object.freeze
Object.preventExtensions() | 使得一个对象无法再添加新的属性 |
---|---|
Object.isExtensible() | 检查是否可以为一个对象添加属性 |
Object.seal() | - 使得一个对象既无法添加新属性,也无法删除旧属性- 实质是把属性描述对象的configurable属性设为false |
Object.isSealed() | 检查一个对象是否使用了Object.seal方法 |
Object.freeze() | 使得一个对象无法添加新属性、无法删除旧属性、也无法改变属性的值,使得这个对象实际上变成了常量 |
Object.isFrozen() | 检查一个对象是否使用了Object.freeze方法 |
💡 BUG:可以通过改变原型对象,来为对象增加属性;
如果属性值是对象,上面这些方法只能冻结属性指向的对象,而不能冻结对象本身的内容
Array
是 JavaScript 的原生对象,同时也是一个构造函数,可以用它生成新的数组。
valueOf(),toString() | - valueOf方法是一个所有对象都拥有的方法,表示对该对象求值- toString方法也是对象的通用方法,数组的toString方法返回数组的字符串形式。 |
---|---|
push(),pop() | 增加or删除数组最后一个元素,会改变原数组 |
shift(),unshift() | 增加or删除数组第一个元素,会改变原数组 |
concat() | 用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。 |
reverse() | 颠倒排列数组元素,返回改变后的的数组 |
slice() | 提取目标数组的一部分,返回一个新数组,原数组不变。 |
splice() | 删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。 |
sort() | 默认按字典顺序对数组成员排序,arr.sort([compareFunction])用来指定按某种顺序进行排列的函数。 |
map() | 将数组的所有成员依次传入参数函数,把每一次的执行结果组成一个新数组返回 |
forEach() | 同map相似,但不返回值,只操作数据 |
filter() | 过滤数组成员,满足条件的成员组成一个新数组返回。 |
reduce(),reduceRight() | 依次处理数组的每个成员,最终累计为一个值 |
indexOf(),lastIndexOf() | 返回给定元素在数组中第一次/最后一次出现的位置 |
所谓“包装对象”,指的是与数值、字符串、布尔值分别相对应的Number
、String
、Boolean
三个原生对象。这三个原生对象可以把原始类型的值变成(包装成)对象。
作为构造函数,它主要用于生成布尔值的包装对象实例。
if (new Boolean(false)) {//所有对象对应的布尔值都是true
console.log('true');
} // true
if (new Boolean(false).valueOf()) {//返回实例对应的初始值
console.log('true');
} // 无输出
Boolean
对象除了可以作为构造函数,还可以单独使用,将任意值转为布尔值。这时Boolean
就是一个单纯的工具方法。
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean('') // false
Boolean(NaN) // false
Boolean(1) // true
Boolean('false') // true
Boolean([]) // true
Boolean({}) // true
Boolean(function () {}) // true
Boolean(/foo/) // true
💡 使用双重的否运算符(!
)也可以将任意值转为对应的布尔值。
作为构造函数时,它用于生成值为数值的对象。作为工具函数时,它可以将任何类型的值转为数值。
Number
对象拥有以下一些静态属性
Number.POSITIVE_INFINITY // Infinity
Number.NEGATIVE_INFINITY // -Infinity
Number.NaN // NaN
Number.MAX_VALUE
// 1.7976931348623157e+308
Number.MAX_VALUE < Infinity
// true
Number.MIN_VALUE
// 5e-324
Number.MIN_VALUE > 0
// true
Number.MAX_SAFE_INTEGER // 9007199254740991
Number.MIN_SAFE_INTEGER // -9007199254740991
Number
对象有4个实例方法,都跟将数值转换成指定格式有关。
Number.prototype.toString() | 将数值转换为字符串形式;可以接受一个参数表示输出的进制; |
---|---|
Number.prototype.toFixed() | 先将一个数转为指定位数的小数,然后返回这个小数对应的字符串 |
Number.prototype.toExponential() | 将一个数转为科学计数法形式;其参数是小数点后有效数字的位数 |
Number.prototype.toPrecision() | 将一个数转为指定位数的有效数字 |
Number.prototype.toLocaleString() | 接受一个地区码作为参数,返回一个字符串,表示当前数字在该地区的当地书写形式。还可以用地区码、style属性等 |
String
对象是 JavaScript 原生提供的三个包装对象之一,用来生成字符串对象
除了用作构造函数,String
对象还可以当作工具方法使用,将任意类型的值转为字符串。
var s1 = 'abc'; //字符串
var s2 = new String('abc'); //字符串对象
typeof s1 // "string"
typeof s2 // "object"
s2.valueOf() // "abc"
// 字符串对象是一个类似数组的对象,有数值键和length属性
new String('abc')
// String {0: "a", 1: "b", 2: "c", length: 3}
(new String('abc'))[1] // "b"
String.fromCharCode()
:参数是一个或多个数值,代表 Unicode 码点,返回值是这些码点组成的字符串。
String.fromCharCode() // ""
String.fromCharCode(97) // "a"
String.fromCharCode(104, 101, 108, 108, 111) // "hello"
字符串实例的length
属性返回字符串的长度
'abc'.length // 3
实例方法
String.prototype.charAt() | 返回指定位置的字符,参数是从0开始编号的位置;可以用数组下标代替 |
---|---|
String.prototype.charCodeAt() | 返回字符串指定位置的 Unicode 码点(十进制表示),相当于String.fromCharCode()的逆操作 |
String.prototype.concat() | 用于连接两个字符串,返回一个新字符串,不改变原字符串。 |
String.prototype.slice() | 从原字符串取出子字符串并返回,不改变原字符串。第二个参数是结束位置 |
String.prototype.substring() | 从原字符串取出子字符串并返回,不改变原字符串第二个参数是结束位置【优先使用slice方法】 |
String.prototype.substr() | 从原字符串取出子字符串并返回,不改变原字符串第二个参数是子字符串的长度 |
String.prototype.indexOf(),String.prototype.lastIndexOf() | 确定一个字符串在另一个字符串中第一次/最后一次出现的位置 |
String.prototype.trim() | 去除字符串两端的空格/制表符/换行符/回车符,返回一个新字符串,不改变原字符串 |
String.prototype.toLowerCase()String.prototype.toUpperCase() | 都返回一个新字符串,不改变原字符串。 |
String.prototype.match() | 确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串。如果没有找到匹配,则返回null |
String.prototype.search(),String.prototype.replace() | - 用法基本等同于match,返回值为匹配的第一个位置。如果没有找到匹配,返回-1。 replace方法用于替换匹配的(第一个)子字符串 |
String.prototype.split() | - 按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。 接受第二个参数,限定返回数组的最大成员数。 |
String.prototype.localeCompare() | 比较两个字符串。通过返回值与0的大小比较判断两个字符串的大小 |
Math
是 JavaScript 的原生对象,提供各种数学功能。该对象不是构造函数,不能生成实例,所有的属性和方法都必须在Math
对象上调用。
Math.E // 2.718281828459045
Math.LN2 // 0.6931471805599453
Math.LN10 // 2.302585092994046
Math.LOG2E // 1.4426950408889634
Math.LOG10E // 0.4342944819032518
Math.PI // 3.141592653589793
Math.SQRT1_2 // 0.7071067811865476
Math.SQRT2 // 1.4142135623730951
Math对象的一些静态方法
Math.abs()
:绝对值Math.ceil()
:向上取整Math.floor()
:向下取整Math.max()
:最大值Math.min()
:最小值Math.pow()
:幂运算,返回以第一个参数为底数、第二个参数为指数的幂运算值Math.sqrt()
:平方根,返回参数值的平方根。如果参数是一个负值,则返回NaN
Math.log()
:自然对数,返回以e
为底的自然对数值Math.exp()
:e
的指数Math.round()
:四舍五入Math.random()
:随机数,返回0到1之间的一个伪随机数,可能等于0,但是一定小于1// 任意范围的随机数生成函数
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
// 任意范围的随机整数生成函数
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Math
对象还提供一系列三角函数方法
Math.sin()
:返回参数的正弦(参数为弧度值)Math.cos()
:返回参数的余弦(参数为弧度值)Math.tan()
:返回参数的正切(参数为弧度值)Math.asin()
:返回参数的反正弦(返回值为弧度值)Math.acos()
:返回参数的反余弦(返回值为弧度值)Math.atan()
:返回参数的反正切(返回值为弧度值)Date
对象是 JavaScript 原生的时间库。它以国际标准时间(UTC)1970年1月1日00:00:00作为时间的零点,可以表示的时间范围是前后各1亿天(毫秒)
1
,小时、分钟、秒钟和毫秒的默认值都是0
// 参数为时间零点开始计算的毫秒数
new Date(1378218728000)
// Tue Sep 03 2013 22:32:08 GMT+0800 (CST)
// 参数为日期字符串
new Date('January 6, 2013');
// Sun Jan 06 2013 00:00:00 GMT+0800 (CST)
// 参数为多个整数,年和月是不能省略的,其他参数都可以省略的。
// 代表年、月、日、小时、分钟、秒、毫秒
new Date(2013, 0, 1, 0, 0, 0, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
Date.now() | 返回当前时间距离时间零点(1970年1月1日 00:00:00 UTC)的毫秒数 |
---|---|
Date.parse() | 解析日期字符串,返回该时间距离时间零点的毫秒数。 |
Date.UTC() | 接受年、月、日等变量作为参数,返回该时间距离时间零点的毫秒数 |
【UTC:世界标准时间】
Date
的实例对象的方法,除了valueOf
和toString
,可以分为以下三类。
to
类:从Date
对象返回一个字符串,表示指定的时间。get
类:获取Date
对象的日期和时间。set
类:设置Date
对象的日期和时间。valueOf
方法返回实例对象距离时间零点(1970年1月1日00:00:00 UTC)对应的毫秒数。to
类方法Date.prototype.toString() | toString方法返回一个完整的日期字符串。 |
---|---|
Date.prototype.toUTCString() | 返回对应的 UTC 时间 |
Date.prototype.toISOString() | 返回对应UTC时间的 ISO8601 写法 |
Date.prototype.toJSON() | 返回一个符合 JSON 格式的 ISO 日期字符串,与toISOString方法的返回结果完全相同。 |
Date.prototype.toDateString() | 返回日期字符串(不含小时、分和秒) |
Date.prototype.toTimeString() | 返回时间字符串(不含年月日) |
以下三种方法,可以将 Date 实例转为表示本地时间的字符串。
Date.prototype.toLocaleString()
:完整的本地时间。Date.prototype.toLocaleDateString()
:本地日期(不含小时、分和秒)。Date.prototype.toLocaleTimeString()
:本地时间(不含年月日)。get
类方法getTime()
:返回实例距离1970年1月1日00:00:00的毫秒数,等同于valueOf
方法。getDate()
:返回实例对象对应每个月的几号(从1开始)。getDay()
:返回星期几,星期日为0,星期一为1,以此类推。getFullYear()
:返回四位的年份。getMonth()
:返回月份(0表示1月,11表示12月)。getHours()
:返回小时(0-23)。getMilliseconds()
:返回毫秒(0-999)。getMinutes()
:返回分钟(0-59)。getSeconds()
:返回秒(0-59)。getTimezoneOffset()
:返回当前时间与 UTC 的时区差异,以分钟表示,返回结果考虑到了夏令时因素。Date
对象还提供了这些方法对应的 UTC 版本,用来返回 UTC 时间。getUTC*
计算本年度还剩多少天
function leftDays() {
var today = new Date();
var endYear = new Date(today.getFullYear(), 11, 31, 23, 59, 59, 999);
var msPerDay = 24 * 60 * 60 * 1000;
return Math.round((endYear.getTime() - today.getTime()) / msPerDay);
}
get
类方法Date
对象提供了一系列与get*方法对应的set*
方法,用来设置实例对象的各个方面。但是没有setDay
—是计算出来的而非设置
setDate(date)
:设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳。setFullYear(year [, month, date])
:设置四位年份。setHours(hour [, min, sec, ms])
:设置小时(0-23)。setMilliseconds()
:设置毫秒(0-999)。setMinutes(min [, sec, ms])
:设置分钟(0-59)。setMonth(month [, date])
:设置月份(0-11)。setSeconds(sec [, ms])
:设置秒(0-59)。setTime(milliseconds)
:设置毫秒时间戳。set*
系列方法除了setTime()
,都有对应的 UTC 版本,即设置 UTC 时区的时间。正则表达式*(regular expression)*是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本。
// 使用字面量,以斜杠表示开始和结束【在编译时新建】
var regex = /xyz/;
// 使用RegExp构造函数【在运行时新建】
var regex = new RegExp('xyz');
// 正则表达式/xyz/有一个修饰符i
var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;
g
全文查找,i
忽略大小写,m
多行查找/cat/.test('cats and dogs') // true
RegExp.prototype.test()
g
修饰符,则每一次test
方法都从上一次结束的位置*(lastindex)*开始向后匹配。var s = '_x_x';
var r1 = /x/;
var r2 = /y/;
r1.exec(s) // ["x"]
r2.exec(s) // null
// 组匹配
var s = '_x_x';
var r = /_(x)/;
r.exec(s) // ["_x", "x"]
RegExp.prototype.exec()
null
exec()
方法的返回数组还包含以下两个属性:
input
—整个原字符串index
—模式匹配成功的开始位置字符串的实例方法之中,有4种与正则表达式有关。
String.prototype.match()
:返回一个数组,成员是所有匹配的子字符串。String.prototype.search()
:按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。String.prototype.replace()
:按照给定的正则表达式进行替换,返回替换后的字符串。String.prototype.split()
:按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。/c.t/ //c.t匹配c和t之间包含任意一个字符的情况
// test必须出现在开始位置
/^test/.test('test123') // true
// test必须出现在结束位置
/test$/.test('new test') // true
/11|22/.test('911') // true
\r
)、换行(\n
) 、行分隔符\u2028
)和段分隔符(\u2029
)以外的所有字符。(一个)^
、.
、[
、$
、(
、)
、|
、*
、+
、?
、{
和\
RegExp
方法生成正则对象,需要两个斜杠进行转义:作为字符串参数先被转义一次,再被正则表达式转义一次[]
:有一系列字符可供选择,只要匹配其中一个就可以了。
[^]
,就表示匹配一切字符,其中包括换行符[abc]
可以写成[a-c]
\d
相当于[0-9]
。\D
匹配所有0-9以外的字符,相当于[^0-9]
。\w
匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
。\W
相当于[^A-Za-z0-9_]
。\s
匹配空格(包括换行符、制表符、空格符等),相等于[ \t\r\n\v\f]
。\S
相当于[^ \t\r\n\v\f]
。\b
匹配词的边界。\B
匹配非词边界,即在词的内部。{}
)表示。类似于区间的形式?
== {0,1}
*
== {0,}
+
== {1,}
'abb'.match(/ab*/) // ["abb"] 贪婪模式
'abb'.match(/ab*?/) // ["a"]
'abb'.match(/ab?/) // ["ab"]
'abb'.match(/ab??/) // ["a"]
💡 贪婪模式:最大可能匹配,即匹配到下一个字符不满足匹配规则为止
非贪婪模式:最小可能匹配。只要一发现匹配,就返回结果,不要往下检查。
将贪婪模式改为非贪婪模式,可以在量词符后面加一个问号。
修饰符:模式的附加规则,放在正则模式的最尾部;可以单个使用,也可以多个一起使用
g
修饰符:全局匹配;每次都是从上一次匹配成功处,开始向后匹配i
修饰符:忽略大小写m
修饰符:多行模式multiline;加上m
修饰符以后,^
和$
会识别换行符(\n
)组匹配:正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容。
g
修饰符,否则match
方法不会捕获分组的内容\n
引用括号匹配的内容,n
是从1开始的自然数,表示对应顺序的括号\n
指向从外到内//组匹配网页标签
var tagName = /<([^>]+)>[^<]*<\/\1>/;
tagName.exec("bold")[1]
// 'b'
//捕获带有属性的标签
var html = 'Helloworld';
var tag = /<(\w+)([^>]*)>(.*?)<\/\1>/g;
var match = tag.exec(html);
match[1] // "b"
match[2] // " class="hello""
match[3] // "Hello"
match = tag.exec(html);
match[1] // "i"
match[2] // ""
match[3] // "world"
(?:x)
:不返回该组匹配的内容var m = 'abc'.match(/(?:.)b(.)/);
m // ["abc", "c"]
// 第一个括号是非捕获组,所以最后返回的结果中没有第一个括号,只有第二个括号匹配的内容。
x(?=y)
称为先行断言,x
只有在y
前面才匹配,y
不会被计入返回结果。x(?!y)
称为先行否定断言,x
只有不在y
前面才匹配,y
不会被计入返回结果。JSON 格式(JavaScript Object Notation )是一种用于数据交换的文本格式,目的是取代繁琐笨重的 XML 格式。
null
、空数组和空对象都是合法的 JSON 值。JSON 对值的类型和格式的规定
null
(不能使用NaN
, Infinity
, Infinity
和undefined
)。JSON
对象是 JavaScript 的原生对象,用来处理 JSON 格式数据。它有两个静态方法:JSON.stringify()
和JSON.parse()
JSON.stringify()
用于将一个值转为 JSON 字符串,可以被JSON.parse()
方法还原
undefined
、函数或 XML 对象,该属性会被JSON.stringify()
过滤。undefined
、函数或 XML 对象,则这些值被转成null
。此方法的第二个参数
JSON.stringify({0: 'a', 1: 'b'}, ['0'])
// "{"0":"a"}"
JSON.stringify()
的返回值;如果处理函数返回undefined
或没有返回值,则该属性会被忽略。var obj = {a: {b: 1}};
function f(key, value) {
console.log("["+ key +"]:" + value);
return value;
}
//递归处理中,每一次处理的对象,都是前一次返回的值。
JSON.stringify(obj, f)
// []:[object Object]
// [a]:[object Object]
// [b]:1
// '{"a":{"b":1}}'
此方法的第三个函数
// 分行输出
// 第三个属性\t在每个属性前面添加一个制表符,然后分行显示。
JSON.stringify({ p1: 1, p2: 2 }, null, '\t')
// {
// "p1": 1,
// "p2": 2
// }
参数对象的 toJSON() 方法
toJSON()
方法,那么JSON.stringify()
会使用这个方法的返回值作为参数,而忽略原对象的其他属性。var user = {
firstName: '三',
lastName: '张',
get fullName(){
return this.lastName + this.firstName;
},
toJSON: function () {
return {
name: this.lastName + this.firstName
};
}
};
JSON.stringify(user)
// "{"name":"张三"}"
Date
对象就有一个自己的toJSON()
方法。toJSON()
方法可以将正则对象自动转为字符串。JSON.stringify()
默认不能转换正则对象,但设置toJSON()
之后就能转换了var obj = {
reg: /foo/
};
// 不设置 toJSON 方法时
JSON.stringify(obj) // "{"reg":{}}"
// 设置 toJSON 方法时 在正则对象原型上部署toJSON()方法
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/) // ""/foo/""
JSON.parse('{}') // {}
JSON.parse('true') // true
JSON.parse('"foo"') // "foo"
JSON.parse('[1, 5, "false"]') // [1, 5, "false"]
JSON.parse('null') // null
var o = JSON.parse('{"name": "张三"}');
o.name // 张三
JSON.parse("'String'") // illegal single quotes
// SyntaxError: Unexpected token ILLEGAL
function f(key, value) {
if (key === 'a') {
return value + 10;
}
return value;
}
JSON.parse('{"a": 1, "b": 2}', f)
// {a: 11, b: 2}
JSON.parse()
JSON.parse()
方法将报错。JSON.parse()
方法可以接受一个处理函数,作为第二个参数,用法与JSON.stringify()
方法类似。