引用类型是js中非常重要的一种数据格式,js赋予了这种数据格式非常强大的属性以及方法,而且也给出了很大的扩展空间,这使得之后的框架可以在此基础上发展起来
Js中给出的引用类型分为7类,下面一一介绍
Object类型
Object类型是使用最多的一个类型,是存储数据以及传输数据的理想选择
访问对象属性可以用点表示法,也可以使用方括号表示法1
2
3
4
5
6
7
8
9//创建对象
let person = new Object(); //方式一
let person = { //方式二
name: "",
age: 8
}
//访问对象
alert(person.name);
alert(person["name"]);
Array类型
创建数组的方式有很多1
2
3
4
5
6
7let colors = new Array();
let colors = new Array(20);
let colors = new Array("bule");
let colors = Array(20);
let colors = Array("bule");
let colors = ["blue","red","green"];
let colors = [];
可以通过数组的属性length来访问数组,添加数组元素
检测数组
检测对象是否属于数组
- instanceof()
- isArray()
1
2
3
4
5
6if(value instanceof Array){ //ture or false
//执行操作
}
if(Array.isArray(value)){ //ture or false
//执行操作
}
转换方法
把数组转换成为string等其他类型
- valueOf()
- toString()
- toLocaleString()
- join()
1
2
3let colors = ["blue","red","green"];
alert(colors.join(",")); //blue,red,green
alert(colors.join("||")); //blue||red||green
栈方法
数组可以使用下面方法实现栈(LIFO)的数据结构,对数组的末端进行操作
- push()
推入到数组的最后一项 - pop()
移除并取得数组最后一项
队列方法
数组可以使用下面方法实现队列(FIFO)的数据结构,对数组开头和结尾进行操作
- push()
- shift()
移除并取得数组第一项 - unshift()
推入到数组的第一项
重排序方法
对数组中的元素重新排序
- reverse()
反转数组的顺序 - sort()
按升序对数组进行排序,先对数组的每个元素调用toString()的方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21let values = [0,1,5,10,15];
values.sort();
alert(values); //0,1,10,15,5 比较字符
//要实现真正排序,需要写下面的函数
function conmpare(value1,value2){
if(value1 < value2){
return -1;
}
if(value1 > value2){
return 1;
}else{
return 0;
}
}
values.sort(compare);
alert(values); //0,1,5,10,15 升序,若实现降序,将return -1改成return 1即可
//简单的排序函数
function compare(vaule1,value2){
return value2-value1;
}
操作方法
- concat()
连接几个数组,返回一个数组 slice()
基于当前数组创建一个新的数组,接受一个或者两个参数1
2
3let colors = ["blue","red","green","yellow","purple"];
let colors1 = colors.slice(1)); //red,green,yellow,purple
let colors2 = colors.slice(1,4)); //red,green,yellowsplice()
接受两个以上的参数,参数1–>起始位置,参数2–>删除几项,之后的参数表示需要插入的项,splice()方法可以实现对数组元素的删除,插入和替换1
2
3
4
5
6
7
8
9
10
11let colors = ["blue","red","green","yellow","purple"];
//删除
let delete = colors.splice(0,1);
//colors = ["red","green","yellow","purple"] delete = ["blue"]
//插入
let insert = colors.splice(1,0,"orange","black");
//colors = ["red","orange","black","green","yellow","purple"] insert = []空数组
//替换
let replace = colors.splice(1,1,"blue"); //colors = ["red","blue","black","green","yellow","purple"] replace = ["orange"]
位置方法
查找数组中某个元素位于数组中的位置(索引)
- indexOf()
- lastIndexOf()
迭代方法
迭代方法是对函数每一项进行操作,一共为数组定义了5个迭代方法
- every()
对数组每一项运行函数,如果每一项都返回ture,则返回ture - filter()
对数组每一项运行函数,该函数会返回ture的项组成的数组 - forEach()
对数组每一项运行函数,没有返回值 - map()
对数组每一项运行函数,返回每次函数调用的结果组成的数组 - some()
对数组每一项运行函数,如果该函数任意一项返回ture,该函数返回ture1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21let numbers = [1,2,3,4,5,4,3,2,1];
let everyResult = numbers.every(function(item,index,array){
return (item > 2);
}) //everyResult = false
let someResult = numbers.some(function(item,index,array){
return (item > 2);
}) //someResult = ture
let filterResult = numbers.filter(function(item,index,array){
return (item > 2);
}) //filterResult = [3,4,5,4,3]
let mapResult = numbers.map(function(item,index,array){
return (item * 2);
}) //mapResult = [2,4,6,8,10,8,6,4,2]
numbers.forEach(function(item,index,array){
//执行操作
}) //没有返回值
归并方法
可以理解为数组求和(求积)
reduce() reduceRight()两个方法都会遍历数组,一个从数组第一项开始遍历,一个从最后一项开始遍历1
2
3
4let values = [1,2,3,4,5];
let sum = values.reduce(function(prev,cur,index,array){
return prev + cur;
})//sum = 15
第一次执行时,prev = 1,cur = 2
第二次执行是,prev为上一次返回的结果3(prev+cur),cur = 3
Date类型
创建日期对象传入的时间格式必须是毫秒数,所以提供了转换格式的方法
- Date.parse()
- Date.UTC()
1 | //把日期格式转换成为毫秒数 |
继承的方法
与其他引用类型一样,Date类型改写了valueOf(),toString(),toLocaleString()三个方法
valueOf()方法返回时间对应的毫秒数
toString()方法返回带时区信息的日期和时间
toLocaleString()方法返回的不带时区信息的日期和时间
日期格式化方法
- toDateString()
- toTimeString()
- toLocalDateString()
- toLocalTimeString()
- toUTCString()
日期/时间组件方法
方法很多,不一一列举
RegExp类型
使用RegExp类型来支持正则表达式
1 | let expression = /pattern/ flags; |
支持3个flag标志位
- g:全局模式,并非遇到一个匹配项就停止(global)
- i:不区分大小写(case-insensitive)
- m:多行模式(multiline)
pattern的内容比较负责,具体见这篇博客
RegExp实例属性
通过属性可以取得关于模式的各种信息1
2
3
4
5
6
7
8
9
10
11
12
13
14let parttern = /\[bc\]at/i;
let parttern1 = new RegExp("\\[bc\\]at","i");
//global:布尔值,是否设置g标志
alert(parttern.global); //flase
//ignoreCase: 布尔值,是否设置i位
alert(parttern.ignoreCase); //ture
//multiline: 布尔值,是否设置m位
alert(parttern.multiline); //flase
//lastIndex: 整数,表示开始搜索下一个匹配项的字符位置,从0算起
alert(parttern.lastIndex); //0
//source: 正则表达式的字符串表示,按照字面量形式返回
alert(parttern.source); //"\[bc\]at"
alert(parttern1.source); //"\[bc\]at"
RegExp实例方法
exec()
专门为捕获组而设计,接受一个参数(字符串),返回包含第一个匹配信息的数组,没有匹配项是返回null。虽然返回的是数组实例,但是包含两个额外的属性,index和input1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19let text = "cat, bat, sat, fat";
let pattern1 = /.at/;
let pattern2 = /.at/g;
let matches1 = pattern1.exec(text);
alert(matches1.index); //0 匹配项在字符串中的位置
alert(matches1.input); //"cat,bat,sat,fat" 输入字符串
alert(matches1[0]); //"cat"
let matches2 = pattern2.exec(text);
alert(matches2.index); //0
alert(matches2.input); //"cat,bat,sat,fat"
alert(matches2[0]); //"cat"
alert(pattern2.lastIndex); //3
matches2 = pattern2.exec(text);
alert(matches2.index); //5
alert(matches2[0]); //"bat"
alert(pattern2.lastIndex); //8test()方法
接受一个字符串参数,检测目标字符串是否与某个模式匹配,常用在if语句中1
2
3
4
5
6let test = "000-0000-0000";
let pattern = /\d{3}-\d{4}-d{4}/;
if(pattern.test(text)){
//匹配
}valueOf(),toString(),toLocaleString()
valueOf()方法返回正则表达式本身
toString()方法返回正则表达式的字面量
toLocaleString()方法返回正则表达式的字面量
RegExp构造函数属性
括号内为缩写
- input($_) ——最近一次要匹配的字符串
- lastMatch($&) ——最近一次的匹配项
- lastParen($+) ——最近一次匹配的捕获组
- leftContext($`) ——input字符串中lastMatch之前的字符串
- rightContext($’) ——input字符串中lastMatch之后的字符串
- multiline($*) ——是否采用多行模式
1
2
3
4
5
6
7
8
9
10let text = "this has been a short summer";
let patern = /(.)hort/g;
if(pattern.test(text)){
alert(RegExp.input); //this has been a short summer
alert(RegExp.lastMatch); //short
alert(RegExp.lastParen); //s
alert(RegExp.leftContext); //this has been a
alert(RegExp.rightContext); //summer
alert(RegExp.multiline); //flase
}
模式的局限性
RegExp存在一定的局限性,有很多不支持的特性
Function类型
函数实际上是对象,每个函数都是Function的实例,函数是对象,函数名是指针。
函数可以通过++函数声明++语法定义也可以通过++函数表达式++定义函数1
2
3
4
5
6
7
8//函数声明语法定义
function sum (num1, num2){
return num1 + num2;
}
//函数表达式定义
let sum = function(num1, num2){
return num1 + num2;
}
通过函数声明创建的函数会函数声明提升,而通过函数表达式创建的函数只有在执行到所在的代码行时才会被执行。
没有重载(深入理解)
创建两个函数名相同的函数,后面的函数会覆盖前面的函数
作为值的函数
函数名本身就是变量,所以函数也可以作为值来使用1
2
3
4
5
6
7function callSomeFunction(someFunction,someArgument){
return someFunction(someArgument);
}
function add(num){
return num+10;
}
let result = callSomeFunction(add, 10); //20,当要访问函数指针而不执行函数的话,需要用add而不是add()
也可以从函数中返回另一个函数,典型例子:根据对象属性对对象进行排序1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function creatComparisonFunction(propertyName){
return function(object1,object2){
let value1 = object1[propertyName];
let value2 = object2[propertyName];
return value1-value2;
}
}
let data = [{
name: "Z",
age: 12
},{
name: "N",
age: 18
}];
data.sort(creatComparisonFunction("name"));
alert(data[0].name); //N
data.sort(creatComparisonFunction("age"));
alert(data[0].name); //Z
函数内部属性
函数内部有两个特殊的对象:arguments和this
arguments除了保存参数之外,还有一个callee的属性,该属性是一个指针,指向拥有这个arguments的函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//阶乘
function factorial(num){
if(num <= 1){
return 1;
}else{
return num * factorial(num-1);
}
}
//使用callee属性可以解除紧密的耦合关系现象
function factorial(num){
if(num <= 1){
return 1;
}else{
return num * arguments.callee(num-1);
}
}
this引用的是函数执行的环境对象
ES5规范了另外一个函数对象的属性:caller,该属性保存着调用当前函数的函数的引用,caller属性不能被赋值1
2
3
4
5
6
7function outer(){
inner();
}
function inner(){
alert(inner.caller); //alert(arguments.callee.caller);
}
outer(); //执行后显示outer()函数的源代码
函数属性和方法
既然函数是对象,那函数也拥有属性和方法
函数拥有两个属性:
- lengh(函数希望接受参数的数量)
- prototype(保存所以的实例方法,之后详细介绍)
函数包含两个非继承的方法:
- apply()
- call()
两个函数的作用都是在特定的作用域(this)调用函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function sun(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments);
}
function callSum2(num1, num2){
return sum.apply(this, [sum1, sum2]);
}
function callSum3(num1, num2){
return sum.call(this, sum1, sum2)
}
console.log(callSum1(10,10)); //20
console.log(callSum2(10,10)); //20
console.log(callSum3(10,10)); //20
两个函数的强大之处是它们可以扩充函数赖以生存的作用域1
2
3
4
5
6
7
8
9
10
11
12window.color = "red";
let o = {color: "blue"};
function sayColor(){
alert(this.color);
}
// 不同的作用域
sayColor(); //"red"
sayColor(this); //"red"
sayColor(window); //"red"
sayColor(o); //"blue"
另外,函数还有一个方法:bind()
该方法会创建一个函数实例,其this值会绑定到传给bind()函数的值