基本类型的问题
var s1 = "some text";
var s2 = s1.substring(2);
// 等同于
var s = new String("some text");
var s2 = s.substring(2);
s = null;
这个例子中的变量s1
包含一个字符串,字符串当然是基本类型值。而下一行调用了s1
的substring()
方法,并将返回的结果保存在了s2
中。我们知道,基本类型值不是对象,因而从逻辑上讲它们不应该有方法。其实,为了让我们实现这种直观的操作,后台已经自动完成了一系列的处理。
1.创建String
类型的一个实例
2.在实例上调用指定的方法
3.销毁这个实例
另一个例子:
var s3 = "some text";
s3.color = "red";
alert(s3.color); //undefined
试图为字符串s3
添加一个color
属性。问题的原因就是第二行创建的String
对象在第二行执行完之后就被销毁了,第三行代码又创建自己的String
对象,而该对象没有color
属性。
使用new
调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的:
var value = "25";
var number = Number(value); //转型函数
alert(typeof number); //"number"
var obj = new Number(value); //构造函数
alert(typeof obj); //"object"
在这个例子中,变量number
中保存的是基本类型的值25
,而变量obj
中保存的是Number
的实例对象。这个例子也适用于String
类型和Boolean
类型
Array类型
检测数组
-
instanceof
操作符 返回一个布尔值;value instanceof Array
-
Array.isArray(value)
Array对象的静态方法isArray()
返回一个布尔值。
转换方法
大多数情况下3个方法返回的结果一致。
-
valueOf()
返回的还是数组本身 -
toString()
方法 返回由数组中每个值的字符串形式拼接而成的一个以逗号为分隔的字符串 -
toLocaleString()
方法 会调用数组中每一项的toLocaleString()
方法,探后拼接而成的一个以逗号为分隔的字符串。
栈方法
-
push()
:接受一个或多个参数,添加到数组末尾,返回新的数组长度,影响源数组。 -
pop()
:从数组末尾删除一项,返回被删除的项,影响源数组
队列方法
-
shift()
:删除数组中的第一项,返回被删除的项,影响源数组。 -
unshift()
:接受一个或多个参数,添加到数组开头,返回新的数组长度,影响源数组。
截取方法
-
slice()
方法- 接受两个参数(起始位置,结束位置),不会影响到原数组
- 如果
slice()
方法中有一个参数为负数,则用数组的长度加上该数来确定相应的位置。在一个包含5项的数组上调用slice(-2,-1)
与调用slice(3,4)
得到的结果一样。如果结束位置小于起始位置,则返回空数组。
-
splice()
方法- 可以接受3个参数(起始位置,截取个数,插入值),可以用来对数组做增,删,改。会影响到原数组
排序方法
-
reverse()
:反转数组项的顺序,影响原数组 -
sort()
: 用于对数组的元素进行排序。接受一个回调函数作为参数用来定制排序顺序,如果不传参数,默认会对数组的每一项进行字符串形式的大小比较正序排序,会影响到原数组。
位置方法
-
indexOf()
和lastIndexOf()
这个两个方法都接受两个参数:要查找的项和(可选的)表示查找起点位置的索引。这两个方法都返回查找的项在数组中的位置,在没找到的情况下返回-1。要求查找的项必须严格相等(就像使用===一样) -
indexOf()
从数组的开头(下标0)位置向后查找,lastIndexOf()
则从数组的末尾开始向前查找,即使有两个匹配的项,也只会匹配第一个返回其下标。
ES5遍历的方法
以下方法都不会影响到源数组
-
every()
对数组中的每一项运行给定函数,如果该函数对每一项返回true
,则返回true
。返回布尔值 -
filter()
对数组中的每一项运行给定函数,返回该函数会返回true
的项组成的数组。返回过滤后的数组 -
forEach()
对数组中的每一项运行给定函数,没有返回值 -
map()
对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组 -
some()
对数组中的每一项运行给定函数,如果该函数对任一项返回true
,则返回true
。返回布尔值
归并方法
-
reduce()
和reduceRight()
这两个方法都会迭代数组的所有项,然后构建一个最终返回的值;reduce()
方法从数组的从第一项遍历到最后一项,reduceRight()
方法从数组的从最后一项遍历到第一项。- 第一个参数接受一个回调;回调接受4个参数(
prev
[前一项],cur
[当前项],index
[下标],array
[正在遍历的数组]);每次这个回调返回的值都会作为第一个参数prev
传递给下一次的回调。这个回调最后一次遍历返回的值,就作为reduce()
函数的返回值。 - 第二个参数接受一个初始值赋值给
prev
,可选。若不传,则prev
默认为数组的第一项,cur
默认为数组的第二项,可少遍历一次。
- 第一个参数接受一个回调;回调接受4个参数(
String类型
查询方法
-
charAt()
和charCodeAt()
。
这两个方法都接收一个参数,即下标。charAt()
方法以单字符字符串的形式返回给定位置的那个字符,charCodeAt()
返回字符编码。
拼接和截取
concat()
:用于将一或多个字符串拼接起来,返回拼接得到的新字符串。slice(start,end)
:提取字符串的某个部分,并以新的字符串返回被提取的部分。参数为负值时会用字符串的长度加上这个负数。如果第二个参数小于第一个参数,则返回空字符串,如果没有第二个参数,则返回直到结尾的字串。不会影响原字符串。substr(start,length)
:可在字符串中抽取从start
下标开始的指定数目的字符,第一个参数为负值的时候会用字符串的长度加上这个负数,第二个参数为负数的时候,会将其转换为0,也就是会返回一个空字符串,如果没有第二个参数,则返回直到结尾的字串。不会影响原字符串。substring(start,end)
:用于提取字符串中介于两个指定下标之间的字符。不接受负值参数,如果第二个参数小于于第一个参数,会将它们互换位置,如果没有第二个参数,则返回直到结尾的字串。不会影响到原字符串。
位置方法
-
indexOf()
和lastIndexOf()
这两个方法都是从一个字符串中搜索给定的子字符串,然后返子字符串的位置(如果没有找到该子字符串,则返回-1
)。这两个方法的区别在于:indexOf()
方法从字符串的开头向后搜索子字符串,而lastIndexOf()
方法是从字符串的末尾向前搜索子字符串。
String类型与正则相关的匹配方法
match()
方法只接受一个参数,要么是一个正则表达式,要么是一个RegExp
对象,返回一个数组,数组的第一项是与整个模式匹配的字符串,之后的每一项(如果有)保存着与正则表达式中的捕获组匹配的字符串。默认只返回找到的第一个符合要求的内容,如果匹配模式为全局模式,这样就会匹配到所用的内容。search()
这个方法的参数与match()
方法的参数相同,返回字符串中第一个匹配项的索引;如果没有找到匹配项,则返回-1。而且,search()
方法始终是从字符串开头向后查找模式。即使设置为全局匹配模式也只会查找到符合要求的第一个字符串然后返回其下标。split()
,这个方法可以基于指定的分隔符将一个字符串分割成多个子字符串,并将结果放在一个数组中。分隔符可以是字符串,也可以是一个RegExp
对象(这个方法不会将字符串看成正则表达式)。split()
方法可以接受可选的第二个参数,用于指定数组的大小,以便确保返回的数组不会超过既定大小。不用设置全局匹配也会全部拆分。replace()
第一个参数可以是一个RegExp
对象或者一个字符串(这个字符串不会被转换成正则表达式),第二个参数可以是一个用于替换的字符串或者一个函数。replace()
方法返回一个新字符串,不会改变原字符串。
如果replace方法的第一个参数是字符串,那么只会替换第一个子字符串。要想替换所有子字符串,唯一的办法就是提供一个正则表达式,而且要指定全局(g)标志,如果第二个参数是字符串,那么还可以使用一些特殊的字符序列。详情见repalce的高阶用法
trim()方法
该方法用来删除字符串前置及后缀的所有空格,返回一个新的字符串
var s1 = " hello world ";
var s2 = s1.trim();
s2 // "hello world"
Number类型
与
Boolean
类型一样,Number
类型也重写了valueOf()
、toLocaleString()
和toString()
方法。重写后的valueOf()
方法返回对象表示的基本类型的数值,另外两个方法则返回字符串形式的数值。toFixed()
方法会按照指定的小数位返回数值的字符串表示。toExponential()
也接收一个参数,而且该参数同样也是指定输出结果中的小数位数,该方法返回以指数表示法(也称e 表示法)如果你想得到表示某个数值的最合适的格式,就应该使用
toPrecision()
方法。
var num = 10;
alert(num.toFixed(2)); //"10.00" 字符串形式
var num = 10.005;
alert(num.toFixed(2)); //"10.01" 字符串形式
var num = 10;
alert(num.toExponential(1)); //"1.0e+1" 字符串形式
var num = 10;
alert(num.toPrecision(1)); //"1e+2" 字符串形式
alert(num.toPrecision(2)); // 99 字符串形式
alert(num.toPrecision(3)); //99.0 字符串形式
// 因为一位数无法准确地表示99,因此`toPrecision()`就将它向上舍入为100,这样就可以使用一位数来表示它了。
Global对象
ECMAScript
虽然没有指出如何直接访问Global
对象,但Web
浏览器都是将这个全局对象作为window
对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,就都成为了window
对象的属性。
编码解码
encodeURI()
和encodeURIComponent()
方法可以对URI
(Uniform Resource Identifiers
,通用资源标识符)进行编码,以便发送给浏览器。有效的URI
中不能包含某些字符,例如空格。而这两个URI
编码方法就可以对URI
进行编码,它们用特殊的UTF-8 编码替换所有无效的字符,从而让浏览器能够接受和理解。
与encodeURI()
和encodeURIComponent()
方法对应的两个解码方法分别是decodeURI()
和decodeURIComponent()
。
整个URI
使用encodeURI()
, 因为它只换空格;search
值使用encodeURIComponent()
,因为会使用对应的编码替换所有非字母数字字符。
eval()
方法
eval()
方法就像是一个完整的ECMAScript 解析器,它只接受一个参数,即要执行的ECMAScript
(或JavaScript
)字符串。
var msg = "hello world";
eval("console.log(msg)"); //"hello world" 相当于直接执行了console语句
console.log(msg2); //报错 不会输出undefined 因为没有变量提升
eval("var msg2 = 'hello eavl'; ");
需要注意的是:在eval()
中创建的任何变量或函数都不会被提升,因为在解析代码的时候,它们被包含在一个字符串中;它们只在eval()
执行的时候创建。
Math对象
常用静态属性
-
Math.E
--- 自然对数的底数,即常量e的值 -
Math.LN10
--- 10的自然对数 -
Math.LN2
--- 2的自然对数 -
Math.LOG2E
--- 以2为底e的对数 -
Math.LOG10E
--- 以10为底e的对数 -
Math.PI
--- π的值 -
Math.SQRT1_2
--- 1/2的平方根(即2的平方根的倒数) -
Math.SQRT2
--- 2的平方根
min()和max()
-
min()
和max()
方法用于确定一组数值中的最小值和最大值 - 要找到数组中的最大或最小值,可以像下面这样使用apply()方法。
var values = [1, 2, 3, 4, 5, 6, 7, 8];
var max = Math.max.apply(null, values);
舍入方法
-
Math.ceil()
向上取整 -
Math.floor()
向下取整 -
Math.round()
四舍五入
random()方法
用法:随机获取2-10之间的整数
function getRandom(x, y) {
return Math.floor(Math.random() * (y-x+1)+x);
}
getRandom(2,10)
其他方法
-
Math.abs(num)
返回num 的绝对值 -
Math.asin(x)
返回x 的反正弦值 -
Math.exp(num)
返回Math.E 的num 次幂 -
Math.atan(x)
返回x 的反正切值 -
Math.log(num)
返回num 的自然对数 -
Math.atan2(y,x)
返回y/x 的反正切值 -
Math.pow(num,power)
返回num 的power 次幂 -
Math.cos(x)
返回x 的余弦值 -
Math.sqrt(num)
返回num 的平方根 -
Math.sin(x)
返回x 的正弦值 -
Math.acos(x)
返回x 的反余弦值 -
Math.tan(x)
返回x 的正切值
Date() 类型
-
Date.now()
方法:返回表示调用这个方法时的日期和时间的毫秒数。 -
getFullYear()
方法:返回4位数的年份。 -
getMonth()
方法:返回日期中的月份,0~11。 -
setMonth()
方法:设置日期中的月份。超过11则增加年份 -
getDate()
方法:返回日期月份中的天数,1~31。 -
setDate()
方法:设置日期月份中的天数。超过该月应有的天数则增加月份
RegExp类型
标志。 g表示全局模式,i表示不区分大小写,m表示多行模式,即在到达一行文本末尾时继续查找下一行中是否存在于模式匹配的项。
如果使用
new RegExp()
的方式定义正则表达式,接受两个参数,第一个是要匹配的字符串模式,另一个是可选的标志字符串。例如:var reg = new RegExp("[bc]at","i")
是等价于var reg = /[bc]at/i
的。如果用new
的方式定义正则表达式,遇到需要转义的符号,需要使用双重转义。因为new RegExp()
接受的参数都是字符串,所有需要将字符串的\
使用为\\
才能正常使用\
转义的作用。
实例属性
-
global
:布尔值,表示是否设置了g标记。 -
ignoreCase
:布尔值,表示是否设置了i标记。 -
multiline
:布尔值,表示是否设置了m标记。 -
lastIndex
:整数,表示开始搜索下一个匹配项的字符位置,从0算起。 -
source
: 正则表达式的字符串表示。按照字面量形式返回而非传入构造函数new RegExp()
中的字符串模式返回。
实例方法
exec()
方法;接受一个参数,即需要应用正则的字符串。返回包含第一个匹配项信息的数组,数组的第一项是匹配到的第一个字符串,第二项包含与第一个捕获组匹配的内容(正则表达式使用括号就会产生多个捕获组),依次类推。在没有匹配项的情况下返回null
。返回的数组虽然是Array
的实例但包含两个额外的属性index
和input
,其中index
表示匹配项在字符串中的位置,而input
表示应用正则表达式的字符串,即该方法接受的参数。test()
方法,接受一个字符串参数。在模式与该字符串匹配的情况下返回true
,否则返回false
var test1 = "caa,bat,fat,sat";
var reg = /.at/;
var matches = reg.exec(test1);
console.log(matches);
["bat", index: 4, input: "caa,bat,fat,sat", groups: undefined]
0:"bat"
groups:undefined
index:4
input:"caa,bat,fat,sat"
length:1
__proto__:Array(0)
Function类型
函数声明 function test() {}
和 函数表达式 var test = function(){}
的区别:
解析器会率先读取函数声明,并使其在执行任何代码前可以被调用;至于表达式,相当于声明了一个变量存储了一个函数,只有变量的提升,没有函数的提升,必须等到解析器执行到它所在的代码行之后的代码中才能调用它。
test('a'); // "a"
function test(str){
console.log(str)
}
// 而下面的会有不应的结果
test("b") // 报错Uncaught TypeError: test is not a function
var test = function(str){
console.log(str)
}
函数内部的属性
函数内部有两个特殊的对象:arguments
和this
。其中,arguments
主要是保存函数的参数,是一个类数组对象,这个对象有一个callee
的属性,该属性是一个指针,指向函数本身。this
指向函数的执行环境对象。
函数内部还有一个属性caller
,保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为null
,需要使用argument.callee.caller
来访问该函数是被哪个函数调用了
function outer(){
inner();
}
function inner(){
console.log(inner.caller); // 返回outer的函数体。
console.log(arguments.callee.caller); // 与上面的等效,耦合更低而已。
}
outer()
函数属性和方法
length
和prototype
。其中length
属性表示函数希望接收的命名参数的个数,如果使用function fn(...arg){}
扩展运算符来传参,length
属性为0。prototype
属性指向函数的原型对象,所有的实例方法都保存在prototype
原型对象中,但是prototype
是不可枚举的,for...in
无法发现。每个函数都包含两个非继承而来的方法:
apply()
和call()
。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。首先,apply()
方法接收两个参数:一个是在其中运行函数的作用域(this指向),另一个是参数数组。其中,第二个参数可以是Array
的实例,也可以arguments
对象。对于call()
方法而言,它与apply()
的区别仅在于接收参数的方式不同,第一个参数是this
值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用call()
方法时,传递给函数的参数必须逐个列举出来,它们真正强大的地方是能够扩充函数赖以运行的作用域。bind()
方法,接受一个执行函数的作用域和参数,返回一个已经改变this指向的函数,所以与apply()
和call()
的区别是,apply()
和call()
会直接调用该函数,而bind()
只是改变执行作用域,返回新函数,函数的执行发生在新函数调用的时候。