1、函数的引入
把一段代码封装起来,再给它起个名字,可以反复调用,就是函数。
2、函数定义
//函数声明
function fn(){
// 函数体
}
//函数表达式
var fn = function() {
// 函数体
}
函数在定义好之后不会执行,调用之后才会执行,比如上述代码,fn是函数的名字,通过fn()调用,可以执行函数。
Java中方法可以重载,但是js不行,如果方法名相同,后面的方法会覆盖前面的方法。
返回的是 1 ,说明执行了第二个函数,因为两个函数名字相同,第二个把第一个覆盖了。
3、函数的返回值
我们可以使用 return 在函数执行完返回数据,数字,字符串等,当然也可以返回另一个函数。
如果函数没有明确返回数据,则默认返回 undefined。
如果只写一个 return(结束语句) ,后面没跟具体值,也返回 undefined。
4、函数的内置对象 (arguments)
在 js 中,每个函数都会有一个内置对象 arguments ,它保存的是函数传递过程中的所有实参,它可以看作是一个数组,因此也可以进行遍历。
5、匿名函数
所谓匿名函数,就是没有名字的函数。它可以后不能被其他用来调用,但可以自身调用。
(function () {
alert(123);
})();
6、函数是引用数据类型
在 js 中,函数是引用数据类型,可以作为参数传入,也可以作为某函数的返回值。
7、预解析
JavaScript引擎在对JavaScript代码进行解释执行之前,会对JavaScript代码进行预解析,在预解析阶段,会将以关键字var和function开头的语句块提前进行处理。当变量和函数的声明处在作用域比较靠后的位置的时候,变量和函数的声明会被提升到作用域的开头。
注意:预解析提升的只是函数或变量的声明!!!
(1)函数提升
预解析后,等于是这样
(2)变量提升
alert(a);
var a = 1;
上面的代码执行完后结果是 undefined,为啥不是 1呢?
因为预解析只是把函数的声明提前了,预解析后的代码相当于这样
var a;
alert(a);
a = 1;
所以结果是undefined
(3)变量和函数同名
当出现变量声明和函数同名的时候,只会对函数声明进行提升,变量会被忽略。
比如:
alert(foo);
function foo(){}
var foo = 2;
预解析的代码为:
function foo(){}
alert(foo);
foo = 2;
所以输出结果是:
(5)预解析分作用域
function showMsg(){
var msg = 'This is message';
}
alert(msg); // msg未定义
预解析后的代码是:
function showMsg(){
var msg;
msg = 'This is message';
}
alert(msg);
因为msg变量在函数体中,在函数外无法访问,所以会返回未定义。
(7)函数表达式不会提升
func();
var func = function(){
alert("我被提升了");
};
返回结果是 func is not a function。
先看一下预解析后的代码:
var func;
func();
func = function(){
alert("我被提升了");
}
预解析后,func一开始只是一个未被定义的变量,所以func()是不行的。
8、作用域
(1)全局作用域
直接编写在 script 标签之中的JS代码,都是全局作用域;
或者是一个单独的 JS 文件中的。
全局作用域在页面打开时创建,页面关闭时销毁;
在全局作用域中有一个全局对象 window(代表的是一个浏览器的窗口,由浏览器创建),可以直接使用。
所有创建的变量都会作为 window 对象的属性保存。
所有创建的函数都会作为 window 对象的方法保存。
(2)局部作用域
在函数内部就是局部作用域,这个代码的名字只在函数的内部起作用。
调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁;
每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的。
将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
(3)隐式全局变量
声明变量使用var
, 如果不使用var
声明的变量就是全局变量,但是不建议使用全局,我们一般使用局部变量就足够了。
function foo () {
var i1 = 1 // 局部
i2 = 2, // 全局
i3 = 3; // 全局
}