JavaScript学习总结(四)function函数部分

概念

函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。

js支持两种函数:一类是语言内部的函数(如eval()),另一类是自己创建的。

JavaScript 函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它。(该变量的作用域是局部的)。

你可以在不同的函数中使用名称相同的局部变量,因为只有声明过该变量的函数才能识别出该变量。

函数调用

有如下四种调用js函数的方式:

  • 作为函数
  • 作为方法
  • 作为构造函数
  • 通过call()和apply()

返回函数的函数

1
2
3
1. 当函数无明确返回值时,返回的值就是`undefined`

2. 当函数有返回值时,返回值是什么就返回什么。

我们可以通过使用 return 语句实现将函数返回调用它的地方。

在使用return 语句时,函数会停止执行,并返回指定的值。

函数通常会返回一个唯一值,那么这个值也可能是另一个函数:

1
2
3
4
5
6
7
8
9
//函数表达式
var box = function(){
var a=1;
return function(){
alert(a++)
}
alert(a);//永远不会执行
}
alert(box());//弹出"function(){alert(a++)}"

在这里,我们只需将返回值赋值给某个变量,然后就可以像使用一般函数那样调用它了:

1
2
3
4
5
6
7
8
var box = function(){
var a=1;
return function(){
alert(++a)
}
}
var newFunc = box();
newFunc();//2

如果想让返回的函数立即执行,亦可以使用box()()来执行这段代码。

ECMAScript所有函数的参数都是按值传递的,言下之意就是参数不会按引用传递。

PS:如果存在按引用传递的话,那么函数里的那个变量将会是全局变量,在外部也可以访问。

1
2
1)值类型:数值、布尔值、nullundefined
2)引用类型:对象、数组、函数。

引用类型值:指的是那些保存在堆内存中的对象,意思是,变量中保存的实际上只是一个指针,这个指针执行内存中的另一个位置,由该位置保存对象;

创建匿名函数

1
2
3
function(){
return ‘hi’; //单独的匿名函数是无法运行的,就算能运行也无法调用,因为没有名字
}

这种匿名函数的用法在JQuery中非常多。直接声明一个匿名函数,立即使用。用匿名函数的好处就是省得定义一个用一次就不用的函数,而且免了命名冲突的问题,js中没有命名空间的概念,因此很容易函数名字冲突,一旦命名冲突以最后声明的为准。

javascript语言里任何匿名函数都是属于window对象。在定义匿名函数时候它会返回自己的内存地址,如果此时有个变量接收了这个内存地址,那么匿名函数就能在程序里被使用了,因为匿名函数也是在全局执行环境构造时候定义和赋值,所以匿名函数的this指向也是window对象

1
2
3
(function(){
console.log(this === window);//true
})();

把匿名函数自我执行的返回值赋给变量:

1
2
3
4
5
6
7
8
9
10
11
<script type="text/javascript">
var box = (function (){
alert('Lee');
})(); //弹出”Lee”;
alert(box); //弹出 undefined
</script>

var box= (function () {
return 'hi';
})();
console.log(box);//hi

自我执行匿名函数的传参:

1
2
3
4
5
<script type="text/javascript">
(function (age){
alert(age);
})(100); //弹出100
</script>

自执行函数的三种写法

1
2
3
var result = function (){
alert(2);
}();

另一种语法也可得到同样结果:

1
2
3
var result = (function () {
console.log(2);
})();

将函数返回值分配给变量:

1
2
3
var result = (function () {
return 2;
}());

回调函数

回调就是一个函数的调用过程。那么就从理解这个调用过程开始吧。函数a有一个参数,这个参数是个函数b,当函数a执行完以后执行函数b。那么这个过程就叫回调。

其实中文也很好理解:回调,回调,就是回头调用的意思。函数a的事先干完,回头再调用函数b。

这里必须清楚一点:函数b是你以参数形式传给函数a的,那么函数b就叫回调函数。

在jquery里的绝大多数效果函数都涉及到callback函数。
jQuery 效果函数

1
2
3
4
5
<script type="text/javascript">
$("div").show(1000,function(){
//callback function
});
</script>

这里的callback function换成实例可以是:

1
2
3
4
5
<script type="text/javascript">
$("div").show(1000,function(){
console.log("hello world")
});
</script>

方法和函数的区别

1
2
3
4
5
6
7
8
9
10
11
var arr = [1,2,3,4,5]
var a =12; // 变量:自由的
arr.a= 5; //属性:属于一个对象
function show() //函数:自由的
{
alert(‘a’);
}
arr.fn = function() //方法:属于一个对象
{
alert(‘b’);
}

其实方法就是函数,只不过方法是有所属的对象。

我们所熟知的,将函数绑定到click事件

语法:

1
$(selector).click(function)

js全局函数

全局函数与内置对象的属性或方法不是一个概念。全局函数它不属于任何一个内置对象。
JavaScript 中包含以下 7 个全局函数,用于完成一些常用的功能:

1
2
escape( )eval( )isFinite( )isNaN( )parseFloat( )
parseInt( )unescape( )

函数的几个作用

  • 作为一个类构造器使用

    1
    2
    3
    function Class(){}
    Class.prototype={};
    var item=new Class();
  • 作为闭包使用

    1
    2
    3
    (function(){
    //独立作用域
    })();
  • 作为构造函数调用

所谓构造函数,就是通过这个函数生成一个新对象(object)。

1
2
3
4
5
6
7
8
<script type="text/javascript"> 
function Test(){//大写,以区分普通函数
this.x = 10;
}

var obj = new Test();
alert(obj.x); //弹出 10;
</script>

##

原型prototype的定义

  • 在JavaScript中,任何一个函数都有一个prototype属性,指向一个对象。但是原型对于普通函数来说没有任何用处,如果函数是一个构造函数,那么用处极大。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //构造函数。构造函数里面没有任何语句,也就是说,这个构造函数在执行的时候,不会给创建出来的对象添加任何属性。
    function People(){

    }

    //构造函数的原型。我们更改了构造函数的原型,为一个新的对象:
    People.prototype={
    name:"Beme",
    sex:"男",
    age:18
    }

    //当一个对象被new出来的时候,不仅仅执行了构造函数里面的语句,也会把这个函数的__proto__指向构造函数的prototype。
    var xiaoming = new People();

    console.log(xiaoming.__proto__);
    console.log(xiaoming.__proto__ == People.prototype);

    //当我们试图访问name、sex、age属性的时候,身上没有。那么就去查找原型,原型身上有,就当做了自己的属性返回了。
    console.log(xiaoming.name);
    console.log(xiaoming.sex);
    console.log(xiaoming.age);
  • JavaScript中的原型链查找: 当我们试图访问一个对象身上的属性的时候,如果这个对象身上有这个属性,则返回它的值。如果它身上没有这个属性,那么将访问它的原型对象,检测它的原型对象身上是否有这个值,如果有返回它原型对象身上的这个值。

  • 任何一个函数都有原型,原型是一个对象,用prototype来访问。当这个函数是构造函数的时候,new出来的对象,它们的原型对象就是这个构造函数的原型。
    • prototype我们称为“原型”,只有函数有原型
    • proto我们称为“原型对象”,任何对象都有原型对象。

原型的用途

  • 我们定义一个方法的时候,如果写在构造函数里面:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        function People(name,age){
    this.name = name;
    this.age = age;
    this.sayHello = function(){
    alert("你好,我是" + this.name + "我今年" + this.age + "岁了");
    };
    };

    var xiaoming = new People("小明",12);
    var xiaohong = new People("小红",11);

    xiaoming.sayHello();
    xiaohong.sayHello();

实际上这个函数被复制了两份,一份给了xiaoming,一份给了xiaohong。xiaoming和xiaohong这两个实例身上有了相同功能的函数,但是这个函数不是同一个函数!

  • ==一句话:所有的属性要绑在对象身上,而所有的方法,定义在对象的原型对象中(构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性):==
    1
    2
    3
    4
    5
    6
    7
    8
          function People(name,age){
    //构造函数里面,负责定义一些属性,随着构造函数的执行,这些属性将绑定到new出来的对象身上
    this.name = name;
    this.age = age;
    }
    //把所有的方法,定义在原型对象身上:
    People.prototype.sayHello = function(){
    alert("你好,我是" + this.name + "我今年" + this.age + "岁了");9 }

call()和apply()

apply()函数有两个参数:第一个参数是上下文,第二个参数是参数组成的数组。如果上下文是null,则使用全局对象代替。例如:

1
function.apply(this,[1,2,3])

call()的第一个参数是上下文,后续是实例传入的参数序列,例如:

1
function.call(this,1,2,3);

函数的递归

函数的递归,即一个函数在通过名字调用自身的情况下构成的:

通过使用argument.callee代替函数名:

1
2
3
4
5
6
7
8
9
10
//arguments.callee是一个指向正在执行的函数的指针
<script>
function factorial(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
</script>
------ 本文结束 ------
0%