JavaScript-----引用类型
1)Object类型
2)Array类型
3)Date类型
4) RegExp类型
5) Function类型
6) 基本包装类型
7) 单体内置对象
五、Function类型
1)没有重载
ECMAScript中没有函数重载的概念,如果同时声明了两个同名函数,而结果则是后面的函数覆盖了前面的函数
2)函数声明和函数表达式
函数声明:function sum(){
}
函数表达式:var sum=function(num1,num2) {
return num1+num2;
}
为什么要区别函数声明和函数表达式呢,实际上,解析器在向执行环境中加载书籍时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码之前都可以访问,至于函数表达式,则必须等到解析器执行到它所在的代码行,才会正真地被解析执行。
3)作为值的函数
ECMAScript中的函数名本身就是变量,所以函数也可以作为值来是使用。可以从一个函数中返回另一个函数,这是非常有用的技术。
比如,传递给数组sort()方法比较函数要接受两个要比较的值,可是我们还需要用一种方式来指明按照哪个属性为排序。下面的就是解决方案。
function tt(pp) {
return function(object1,object2) {
var value1 =object1[pp];
var value2 =object2[pp];
if(value1<value2) {//从小到大排序
return -1;
}else if(value1>value2) {
return 1;
}else {
return 0;
}
};
}
var data=[
{name: "Zachary",age:28},
{name: "Nicholas",age: 29}
]
data.sort(tt("age"));
console.log(data[0].name);//"Zacjary"
这个函数,看起来是不是有点复杂,其实呢,他就是一个函数中嵌套了另一个函数,而且内部函数前面加了一个return操作符。内部函数接受到pp这个参数后,它会使用方括号,来表示按照哪个类型进行排序。比如上面的value=object[pp],这个意思就是呢,它value的类型,按照这个pp的类型来,然后就能按照指定的类型进行排序了。
当然,上面那个是让age这个属性从小到大排序的,如果想让他从大到小,只需要修改判断语句中的方向即可。
4)函数内部属性
在函数内部,有两个特殊的对象:arguments 和this
首先先说说arguments,看过我之前的博客的应该可以知道,这个是函数内部的一个专门用来存储实参的数组对象,这句话很重要,后面会有很多arguments对象,都是存储实参的数组对象,arguments[0]代表传入的第一个参数,以此类推,不过可以,这个对象还有一个名叫callee的属性,这个属性是一个指针,可以指向拥有这个arguments对象的函数。
function factiorial(num) {
if(num<=1) {
return 1;
}else {
return num*factorial(num-1)
}
}
这个是阶乘函数,递归算法,但是它函数的名字和它里面又调用同名函数,紧紧耦合在一起了,就是我想改一下函数的名字的话,里面的也得一起改,对维护起来也是很麻烦,可以用下面的arguments.callee
function factorial(num) {
if(num<=1) {
reuturn 1;
}else {
return num*arguments.callee(num-1)
}
}
有了上面的arguments.callee()指代函数后,无论我们的函数名字是什么,我们都可以完成函数的递归调用,如下面代码所示
var pp=factorial;
alert(pp(5)) //120
你会不会想到,为啥我要折磨自己,非要把他用作其他的函数名呢?其实呀,这样可以让代码更加灵活,可维护性更高!
好了,说完了arguments,我们来说说this
这个this是干嘛的呢?用官方术语说呢,叫做引用函数据以执行的环境对象。我们来看看下面的代码展示
window.color="black";
function showcolor(){
alert(this.color);
}
showcolor();//black
var newcolor={color:"pink"};
newcolor.showcolor=showcolor;
newcolor.showcolor();//pink
首先我们分析一波,window中定义了color变量为"black",所以呢,当调用函数showcolor的时候,函数所处的环境是在全局作用域中定义的,因此this也是指向全局作用域。当把这个函数赋给newcolor这个变量时,this引用的对象是指向newcolor,因此结果就是pink.
ok,到了最后一个了,我们来看看caller属性是干嘛的。
其实只要记住一点,caller保存着调用当前函数的函数的引用,比如下面代码所示
function aa(){
bb();
}
function bb(){
alert(arguments.callee.caller);
}
aa();
arguments.callee这个调用没忘记吧,这个是用来指向当前的函数的,减少耦合。
这个结果返回的就是aa函数本身。
5)函数属性和方法
ECMAScript中的函数也是对象,因此呢,函数也是有属性和方法的,每个函数都有两个属性:length和prototype.,当然,每个函数也有两个非继承而来的方法 apply()和call()
1))先看看length
,函数的length是什么呢,其实,他代表的是函数的参数个数,如果函数没有参数的话,则返回的是0
function hs(num1,num2){
return num1+num2;
}
alert(hs.length);//返回的结果是2
2))还有一个prototype属性,
这个属性,保存了引用类型所有实例方法,这个属性非常的强大,先提一下哈
3))两个非继承而来的方法 apply()和call(),
这两个方法的用途都是在特定的作用域中调用函数。
首先我们看看apply()
,他接受了两个参数:一个是运行函数的作用域,一个是参数数组,说到参数数组,你想到了啥,如下面所示
function sum(num1,num2){
return num1+num2;
}
function callsum1(num1,num2){
return sum.apply(this,arguments);//arguments也可以换成{num1,num2}
}
alert(callsum1(10,10));
这其中的this呢,其实就是sum()的作用域啦(在这里的话其实传入的是window对象,因为是在全局环境下调用的,在非严格模式下使用函数的apply(),call(),传入null 或者undefined值会被转换为全局对象。在严格模式下,函数的this始终是指定的值,无论指定的是什么值。),arguments是函数内存储实参的数据对象,也就是num1和num2的集合。这样的话,callsum1同样也是调用了sum函数。
我们再来看看call()
,其实呢,他和apply()的区别就在于,他传入的不是arguments对象,而是传入了参数,当然你问我他两有什么区别呢,我只能说这个用法是没什么区别的。如下代码所示
function sum(num1,num2){
return num1+num2;
}
function callsum1(num1,num2){
return sum.call(this,num1,num2);
}
alert(callsum1(10,10));
其实呢,这个用法不是他真正的用法,他还能够扩充函数赖以运行的作用域。
window.color="black";
function showcolor(){
alert(this.color);
}
showcolor();//black
var newcolor={color:"pink"};
showcolor.call(newcolor); //pink
当然,这里的call和apply的用法是一致的。
其实,ECMAScript5也定义了一个方法bind(),这个方法会创建一个函数的实例,其this的值会被绑定到bing()函数的值。如下面代码所示
window.color="black";
function showcolor(){
alert(this.color);
}
showcolor();//black
var newcolor={color:"pink"};
var bindcolor=showcolor.bind(newcolor);
bindcolor();//pink
六、基本包装类型。
什么是基本包装类型呢,前面我们讲到基本数据类型和引用类型,对于引用类型的值,我们可以为其添加属性和方法。但是呢,为了便于操作基本类型值,ECMAScript还提供了3个特殊的引用类型,Boolean,Number,String。你看的没错,他不仅有基本类型的功能,还有引用类型的功能,每当读取一个基本类型值时,后台就会创建一个对应的基本包装北行的对象,让我们能够调用一些方法来操作这些数据。