概念
函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
js
支持两种函数:一类是语言内部的函数(如eval()
),另一类是自己创建的。
在 JavaScript
函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它。(该变量的作用域是局部的)。
你可以在不同的函数中使用名称相同的局部变量,因为只有声明过该变量的函数才能识别出该变量。
函数调用
有如下四种调用js函数的方式:
- 作为函数
- 作为方法
- 作为构造函数
- 通过call()和apply()
返回函数的函数
1 | 1. 当函数无明确返回值时,返回的值就是`undefined`。 |
我们可以通过使用 return
语句实现将函数返回调用它的地方。
在使用return
语句时,函数会停止执行,并返回指定的值。
函数通常会返回一个唯一值,那么这个值也可能是另一个函数:
1 | //函数表达式 |
在这里,我们只需将返回值赋值给某个变量,然后就可以像使用一般函数那样调用它了:
1 | var box = function(){ |
如果想让返回的函数立即执行,亦可以使用box()()
来执行这段代码。
ECMAScript
所有函数的参数都是按值传递的,言下之意就是参数不会按引用传递。
PS:如果存在按引用传递的话,那么函数里的那个变量将会是全局变量,在外部也可以访问。
1 | (1)值类型:数值、布尔值、null、undefined。 |
引用类型值:指的是那些保存在堆内存中的对象,意思是,变量中保存的实际上只是一个指针,这个指针执行内存中的另一个位置,由该位置保存对象;
创建匿名函数
1 | function(){ |
这种匿名函数的用法在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 | var result = function (){ |
另一种语法也可得到同样结果:1
2
3var result = (function () {
console.log(2);
})();
将函数返回值分配给变量:1
2
3var result = (function () {
return 2;
}());
回调函数
回调就是一个函数的调用过程。那么就从理解这个调用过程开始吧。函数a有一个参数,这个参数是个函数b,当函数a执行完以后执行函数b。那么这个过程就叫回调。
其实中文也很好理解:回调,回调,就是回头调用的意思。函数a的事先干完,回头再调用函数b。
这里必须清楚一点:函数b是你以参数形式传给函数a的,那么函数b就叫回调函数。
在jquery里的绝大多数效果函数都涉及到callback函数。
jQuery 效果函数
1 | <script type="text/javascript"> |
这里的callback function
换成实例可以是:1
2
3
4
5<script type="text/javascript">
$("div").show(1000,function(){
console.log("hello world")
});
</script>
方法和函数的区别
1 | var arr = [1,2,3,4,5] |
其实方法就是函数,只不过方法是有所属的对象。
我们所熟知的,将函数绑定到click
事件
语法:1
(selector).click(function)
js全局函数
全局函数与内置对象的属性或方法不是一个概念。全局函数它不属于任何一个内置对象。
JavaScript 中包含以下 7 个全局函数,用于完成一些常用的功能:1
2escape( )、eval( )、isFinite( )、isNaN( )、parseFloat( )、
parseInt( )、unescape( )。
函数的几个作用
作为一个类构造器使用
1
2
3function 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
13function 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
8function 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 | //arguments.callee是一个指向正在执行的函数的指针 |