本章重点
1.使用对象
2.创建并操作数组
3.理解基本的JavaScript类型
4.使用基本类型和基本包装类型
JavaScript引用类型的值是引用类型的一个实例。在ECMAScript中,引用类型是一种数据结构,用于将数据和功能组织在一起。它也常被我们称之为类,但这种称呼并不恰当,因为它还不具备传统的面向对象语言所支持的类和接口等基本结构。
虽然引用类型看起来跟类相似,但他们并不是一个概念。为了避免开,小红书不使用 类 来描述。
对象是某个引用类型的实例。新对象是使用new来和一个构造函数去创建的。但是构造函数本身就是一个函数,只不过该函数是来自创建新对象的目的而定义的。
Object类型
例如:var person = new Object();
person.name = "huihui";
person.age = 2;
var anotherPerson = {
name: "huihui",
age: 1.5
}
这样我们就创建了Obejct引用类型的一个新实例,然后把这个实例赋值给了person这个变量。使用的构造函数是Object,它之给新对象定义了默认的属性和方法。ECMAScript也有很多原始引用类型(例Object),这些便于我们来实现一些常见的计算任务。
我们通过字面量定义对象时实际不会调用Object对象。
除了通过点语法,也可以使用方括号访问属性。
alert(anotherPerson["name"]);
Array类型
js中的数组中的每一项可以是任何类型的数据。
var colors= new Array("blue","red");
var persons = new Array(3);//如果参数是一个数值,那么会创建给定项数的数组,这里创建了长度为3的数组
数组的length属性不是只读的,通过设置这个属性可以给数组的末尾添加和移除元素。如果将length属性设置大于数组项数的值,则新增项被设为undefined。
alert(Array.isArray(persons));//检测变量是不是Array
调用toString方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。实际是调用数组每一项的toString方法,而toLocaleString方法实际是调用数组每一项的toLocaleString方法
alert(colors.toString());
join方法可以使用不同的分隔符来构建字符串。
alert(colors.join('--'))
调用valueOf方法返回数组。
栈方法
push方法接受任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度,而pop方法移除数组最后一项,并返回该项。
队列方法
shift能够移除数组的第一个项并返回该项,同时将数组长度减1。
unshift能够在数组前端添加任意个项并返回新数组的长度并返回新数组的长度。
重排序方法
reverse 反转数组项的顺序
sort 调用每个项的toString方法,得到字符串然后排序,即使每一项都是数值,sort比较的也是字符串。
sort方法可以接受一个比较参数。比较函数接受两个参数,如果第一个参数在前面,应该返回负数。相等返回0,反之返回正数。
var values=[0,12,2,23,44,5];
function compare(pre,next){
return pre-next;
}
alert(values.sort(compare));
操作方法
contact方法创建原数组的副本,然后接收到的参数添加到这个副本的末尾,最后返回新创建的数组。
alert(colors.concat("green"));
slice 一个参数,返回从参数指定位置开始到数组末尾的新数组,两个参数,返回从开始位置到结束位置之间的项,但不包括结束位置。
var values=[0,12,2,23,44,5];
alert(values.slice(1));//12 2 23 44 5
alert(values.slice(1,3));//12 2 23
如果slice方法的参数中有一个负数,则用数组长度加上该数来确定位置。
splice方法
删除,指定两个参数,要删除的第一项的位置和要删除的项数。
插入,三个参数,起始位置,0,要插入的项
替换,三个参数,起始位置,要删除的项数,和要插入的任意数量的项。插入的项数和删除的项数不必相等。
var values=[0,12,2,23,44,5];
values.splice(2,1,13,14);//0 12 13 14 23 44 5
alert(values);
位置方法
indexOf lastIndexOf(从后向前找)查找给定项在数组中的位置
还可以接受一个可选参数,表示要开始找的位置
values.splice(4,0,12);//0 12 13 14 12 23 44 5
alert(values.indexOf(12));//1
alert(values.indexOf(12,3));//4
迭代方法
- every 对数组每一项运行给定方法,每一项都是true则返回true
- filter 对数组每一项运行给定方法,返回true项组成的数组
- map 对数组每一项运行给定方法,返回函数操作结果组成的数组
- forEach 对数组每一项运行给定方法,不返回结果。
- some 对数组每一项运行给定方法,有一项是true则返回true
归并方法
reduce reduceRight 迭代数组的所有项,构建一个最终的返回值。reduce 从头开始 reduceRight从数组末尾开始。
这两个方法接受两个两个参数:一个在每一项上调用的函数,和作为归并基础的初始值。调用的函数接受4个参数:前一个值,当前值,项的索引和数组对象。这个函数的返回值会作为第一个参数传给下一项。
var numbers=[1,2,3,4,5];
var sum=numbers.reduce(function(pre,cur,index,array){
return pre+=cur;
})
alert(sum);
Data类型
var now= new Date();
alert(now);//Mon Aug 01 2016 11:36:11 GMT+0800 (CST)
var someDate=new Date("8/1/2016");
alert(someDate);//Mon Aug 01 2016 11:39:23 GMT+0800 (CST)
var date2 = new Date(Date.UTC(2016,7,1,11,41));
alert(date2);
RegExp类型
var expressions = /pattern/flags;
pattern表示正则表达式,flags标志正则表达式的行为。
g 全局模式,应用与所有字符串,而非发现第一个匹配项立即停止。
i 不区分大小写模式
-
m 多行模式 到达一行末尾时还会继续查找下一行。
还可以使用RegExp构造函数:var pattern3=/.at/gi; var pattern2= new RegExp(".at");
HTML5中规定,字面量和构造函数一样,每次都创建新的RegExp实例。
exec()接受要应用的模式的字符串,返回包含第一个匹配项信息的数组;没有返回null。数组里还有两个额外的属性:index和input index表示匹配项在字符串的位置,input表示应用正则表达式的字符串。
exex()即使设置了g,每次也只会返回一个匹配项。
test() 有匹配返回true。
Function类型
函数实际上是对象,每个函数都是Function类型的实例
两种方式
function sum(number1,number2){
return number1+number2;
}//函数声明 推荐
var sum=function(number1,number2){
return number1+number2;
}//函数表达式
解析器在向执行环境加载数据时,会率先读取函数声明,并使其在执行任何代码之前可访问。函数表达式则必须等到解析器执行到它所在的行,才会真正被执行。
即使声明函数的代码在调用之后,它也能被提升到顶部。
函数内部有两个特殊的对象,arguments和this,arguments有一个callee的属性,指向拥有这个arguments的函数。
function factorial(num){
if(num<1){
return 1
}else{
return num*arguments.callee(num-1);
}
}
this引用的是函数据以执行的环境对象。
caller保存着调用当前函数的函数的引用。
对于引用类型而言,prototype是保存它们所有实例方法的真正所在。
每个函数都包含两个非继承而来的方法,apply和call。
apply接收两个参数,一是在其中运行函数的作用域,另一个是参数数组。call类似,第二个参数数组里的参数必须逐个列举出来。
apply和call真正强大的方法是能够扩充函数赖以运行的作用域。
window.color="red";
var o={color:"blue"};
function sayColor(){
alert(this.color);
}
sayColor();//red
sayColor.apply(o)//blue
bind 创建一个函数实例,其this值会被绑定到bind的参数。
基本包装类型
基本包装类型就是为了方便操作基本类型值,ECMAScript中还提供了三个特殊引用类型:number,string,boolean。
- 每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象
例如
var s1 = 'some text'
var s2 = s1.substring(2)
等于
1、创建String类型的一个实例
2、在实例上调用指定的方法
3、销毁这个实例
var s1 = new String('some text')
var s2 = s1.substring(2)
s1 = null
- 引用类型和基本包装类型的主要区别是对象的生存期
例如
var s1 = 'some text'
s1.color = 'red'
console.log(s1.color) //undefined
Object构造函数也会像工厂方法一样,根据传入值的类型返回相应基本包装类型的实例
var obj = new Object('some text')
console.log(obj instanceof String) //true
Boolean类型
Boolean类型的实例重写了valueOf()方法,返回基本类型值true或false,重写了toString()方法
布尔表达式中的所有对象都会被转换为true
var falseObject = new Boolean(false)
var result = falseObject && true
console.log(result) //true
var falseValue = false
result = falseValue && true
console.log(resulet) //false
typeof的表现方式
- 基本类型:
console.log( typeof falseValue ) //boolean
- 对象类型 :
console.log( typeof falseObject ) //object
Number类型
Number同理
String类型
- charAt()
返回给定位置的字符
var string = 'hello world'
console.log(string.charAt(1)) //'e'
- charCodeAt()
返回给定位置的字符编码
var string = 'hello world'
console.log(string.charCodeAt(1)) //'101'
- concat()
原数组不变,返回一个新数组
concat()可以接受任意多个参数
var stringValue = 'hello'
var result = stringValue.concat('world')
console.log(result) //'hello world'
console.log(stringValue) //'hello'
- length
即使字符串中包含双字节字符(不是占一个字节的ASCII字符),每个字符也仍然算一个字符 -
slice()、substr()、substring()
-
slice() 和 substring()的第二个参数指定的是子字符串最后一个字符后面的位置。
substr()的第二个参数指定的是返回的字符个数 - 当这三个方法的参数是负值的情况下,他们的行为就不尽相同了
- slice()方法会将传入的负值与字符串的长度相加,第二个参数转换为7
- substr()方法将负的第一个参数加上字符串的长度,而将负的第二个参数转换为0
- substring()方法会把所有的负值参数都转换为0
-
slice() 和 substring()的第二个参数指定的是子字符串最后一个字符后面的位置。
var string = 'hello world'
console.log(string.slice(-3)) //'rld'
var string = 'hello world'
console.log(string.substr(3)) //'rld'
console.log(string.substr(3,-4)) //'空字符串'
var string = 'hello world'
console.log(string.substring(-3)) //'hello world'
console.log(string.substring(3,-4)) //'hel'
字符串位置方法
- indexOf()
从前往后 - lastIndexOf()
从后往前
var string = 'hello world'
console.log(string.indexOf('o')) //4
console.log(string.lastIndexOf('o')) //7
可以循环调用indexOf()或lastIndexOf()来找到所有匹配的子字符串
var string = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit'
var positions = new Array()
var pos = stringValue.indexOf('e', pos + 1)
while(pos > -1){
positions.push(pos)
pos = string.indexOf('e', pos + 1)
}
console.log(positions) //'3,24,32,35,52'
- trim()
删除前后空格,原始字符串的前后空格保持不变,返回字符串的副本
字符串大小写转换方法
toLowerCase()、toLocaleLowerCase()
转换为小写
LocaleLowerCase是针对特定地区的实现,少数语言会为Unicode大小写转换应用特殊的规则toUpperCase()、toLocaleUpperCase()
转换为小写 同上
字符串的模式匹配方法
String类型定义了几个用于在字符串中匹配模式的方法
-
match()
match()方法只接受一个参数,要么是一个正则表达式,要么是RegExp对象
返回了一个数组,数组的第一项是与整个模式匹配的字符串,之后每一项保存着与正则表达式中的捕获组匹配的字符串。
var text = 'cat, bat, sat, fat'
var pattern = /.at/
var matches = text.match(pattern)
//与pattern.exec(text)相同
console.log(matches.index) //0
console.log(matches[0]) //'cat'
console.log(pattern.lastIndex) //0
-
search()
search()方法返回字符串中第一个匹配项的所有;如果没有找到匹配项,则返回-1
从字符串开头向后查找模式
var text = 'cat, bat, sat, fat'
var pos = text.search(/at/)
console.log(pos) //1
-
replace()
替换
第一个参数可以是一个RegExp对象或者一个字符串(这个字符串不会转换成正则表达式)
第二个参数可以是一个字符串或者一个函数
如果想替换所有匹配的字符串,唯一的办法就是提供一个正则表达式
var text = 'cat, bat, sat, fat'
var result = text.replace('at','ond')
console.log(result) //'cond,bat,sat,fat'
result = text.replace(/at/g, 'ond')
console.log(result) //'cond,bond,sond,fond'
如果第二个参数是字符串,还可以用一些特殊的字符序列
<匹配整个模式的子字符串
- /article>匹配的子字符串之前的子字符串
- <article class="_2rhmJa"匹配的子字符串之后的子字符串
- $n匹配第n个捕获组的子字符串
- $nn匹配第nn个捕获组的子字符串
var text = 'cat, bat, sat, fat'
result = text.replace(/(.at)/g,'word($1)')
replace()的第二个参数也可以是一个函数。
在只有一个匹配项的情况下,会向这个函数传递3个参数:模式的匹配项、模式匹配项在字符串中的位置和原始字符串
function htmlEscape(text){
return text.replace(/[<>'&]/g, function(match,pos,originalText){
switch(match){
case '<':
return '<'
case '>':
return '>'
case '&':
return '&'
case '\':
return '"'
}
})
}
- split()
split()返回一个数组
split()方法可以接受可选的第二个参数,用于指定数组的大小
单体内置对象
URI(标识、定位任何资源的字符串)
- encodeURI()
不会对本身属于URI的特殊字符进行编码
var uri = 'http://www.wrox.com/illegal value.htm#start'
console.log(encodeURI(uri))
console.log(encodeURIComponent(uri))
- encodeURIComponent()
则会对它发现的任何非标准字符进行编码
eval()
eval()中创建的任何变量或函数都不会被提升,在解析代码的时候,他们被包含在一个字符串中