函数的作用就是封装一段JavaScript代码,让开发者可以通古简单的方式使用这段代码
在几乎所有的编程语言中,都有函数这一概念,并且没中语言本身都继承了丰富的函数,这类函数被称为系统函数或者内置函数,系统函数在语言设计时就已经定义好了,开发者根据语言的开发手册学习使用就可以
js的系统函数可以分为数学函数、时间函数、字符串函数等
自定义函数就是开发者自己定义的函数,其代码处理逻辑有开发者指定,用来满足项目开发中一些特性的需求
声明函数大致分为函数名、形式参数、函数体
函数名与标识符的定义规则一致
形式参数相当于一个占位符,不具有实际作用,它是可选的,和它对应的就是实际参数
函数体就是我们可以重复使用的代码,我们可以将重要的代码编写在其中,通常的情况下函数体中的return用于返回一个数据值,当然也可以单纯的执行一段语句。
// 函数定义语法
function 函数名(形式参数1,形式参数2,...形式参数n){
语句;
return 返回值;
}
// 例子
function demo(){
var count = 0;
for(var i=0;i<10;i++){
count +=1;
}
return count;
}
// 函数调用的语法
函数名(实际参数1,实际参数2,...实际参数n);
// 注意:
// 函数在创建之后不会自动指定,只有在调用之后才会执行函数体中的语句,概括的说:不调用、不执行
参数就是用来让函数更灵活的,参数分为形式参数和实际参数,形式参数不具备实际值,仅仅作为占位符存在,用于函数体的语句中,实际参数具有实际值,在调用时会对形式参数进行一一对应赋值,然后被用于函数体的语句中
function demo(num){
var count = 0;
for(var i=0;i<num;i++){
count+=i;
}
return count;
}
console.log(demo(10));
// 上述例子设置了形参num,当我们不传递实参时,num就没有被赋值,会默认undefined,在比较运算中会自动转换为数值0,当我们传递多个实参时,没有形参与之对应会默认被抛弃,程序都可以执行
// es6中可以给形参一个默认值
function demo(num =10){
var count = 0;
for(var i=0;i<num;i++){
count += i;
}
return count;
}
对于函数外部而言,函数内部是不可见的,它们需要一种沟通机制,参数就是它们沟通的桥梁,通过参数外部语句可以传递不同的数据给函数处理,参数也是一种变量,但这种变量只能被函数内部的语句使用,并在函数调用时被赋值,除了参数返回值也是函数的组成部分,参数时外部语句对函数内部语句的信息传递,而返回值正好相反,和参数一样return语句并不是必要的,也许函数体内的语句只是想显示一句话而已,那就不需要返回值
除一般函数外,函数具有多种特殊形式,下面我们就分别介绍一下
表达式最终会返回一个值,函数表达式返回的数值就是其本身,其格式与函数声明语句一致,只不过函数表达式可以将函数名省略
function(){
函数体;
return 返回值;
}
// 自执行函数就是在脚本执行时进行自动调用,自执行函数的创建步骤和执行步骤时一起进行的
// 而且仅在程序中执行一次,格式如下:
(function(参数1,参数2,...参数n){
语句;
})([参数1,参数2,...参数n]);
// 自执行函数分为两个部分,第一对小括号内是一个匿名函数,第二对向括号内是传入的实参
// 回调函数实质就是通过时间或函数被触发来执行的
<button onclick="clickButton()">按钮</button>
<script>
function clickButton(){
alert("您点击了按钮");
}
</script>
// 在js中递归函数的实现方式就是在函数体中调用其函数本身,也可以称为函数的自调用
// 实现10的阶乘 10x9x8x7x6x5x4x3x2x1
function jiecheng(num){
if(num < = 1){
return 1;
}
return num * jiecheng(num - 1);
}
console.log(num(10));
构造函数经常被用于创建内置对象,比如创建一个字符串new String()、创建一个数组new Array()
它通常作为一种创建方式存在,但其实构造函数不仅仅是一种创建方式、也是一种初始化的方式
在网页中js代码默认在全局作用域下,与之关联的对象就是window对象,当我们在创建函数时,函数就是一个局部作用域,与之关联的对象就是这个函数对象,创建一个函数相当于在全局作用域下开辟一块区域用作局部作用域,创建多个函数意味着创建了多个局部作用句,同时在函数中可以嵌套创建函数,这意味着在局部作用域下还可以拥有若干个局部作用域
在全局和局部作用域下声明的变量分别被称为全局变量和局部变量,它们存储在与作用域关联的对象中两者的区别:
1、在全局作用域下声明的变量具有全局性,在任意位置都可以获取,包括在局部作用域下
2、在局部作用域下声明的变量具有局部性,仅能在该作用域下使用,在全局作用域下无法使用
3、全局变量和局部变量同名时可共存
// 全局变量在任何位置都可以访问
var name = "知数SEO";
function demo(){
alert(name);
}
demo();
// 上述例子中执行的步骤是:
// 第一步:寻找该作用域下的局部变量,若找到则返回对应值,否则回到上一级作用域下寻找
// 第二步:进入上一级作用域,寻找同名的变量,若找到返回对应的值,否则返回undefined
// 第三步:积蓄执行第二步,知道到达顶级作用域
// 局部变量仅能在局部作用域下使用
function demo(){
var name = "知数SEO";
console.log(name);
}
demo();
console.log(name);
// 函数最重要的一个特点就是不调用不执行
// 全局变量的生命周期较长,只有脚本结束或认为删除才会清除全局变量的内存占用
// 局部变量的生命周期较短,当函数执行时局部变量产生,函数执行完毕后局部变量会被回收,清空内存
闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数)因而这些变量也是该表达式的一部分
通俗的讲,在js中每个函数都是一个闭包函数,因为函数生成了一个局部作用域,在局部作用域下可以声明一系列的变量、函数,同时可以在局部作用域下访问已声明的变量和函数,并且嵌套函数中服从作用域链的规则,而这种操作在 局部作用域外是无法实现的,那么这个由作用域范围定界,生成的一块保存若干变量和函数的数据包就可以称为一个闭包
闭包是将一些列变量和变量环境进行保存,是为了在外部访问到闭包中的变量
function demo(){
var name = "知数SEO";
return function(){
alert(name);
}
}
demo();
// 闭包的两个特性
// 一、可以读取局部变量
// 二、将值爆存在内存中(缺陷就是容易引发内存泄漏)
function add(){
var count = 0; // 初始化局部变量
return function(){
return count++; // 局部变量累加1
}
}
var getCount = add(); // 创建一个闭包
console.log(add()); // 结果为0
console.log(add()); // 结果为1
console.log(add()); // 结果为2
rest参数(形式为 …变量名)用于获取函数的多余参数,这样就不需要引入arguments
对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中
function add(...valuse){
// 声明局部变量用于保存数值
let num = 0;
// 循环参数遍历数据
for(var val in values){
sum += val;
}
// 返回总和
return sum;
}
// 调用函数
var num = add(2,3,4);
console.log(num); // 输出 9
// 需要注意的是rest函数之后不能再有其他参数(只能是最后一个参数),否则会报错
// 在ES6中允许使用肩头=>定义函数
var f = v=>v;
//等同于
var f = function(v){
return v;
}
// 如果箭头函数不需要参数
var f = ()=>5;
//等同于
var f = function(){
return 5;
}
// 如果箭头函数需要多个参数
var f = (num1,num2)=>num1+num2;
// 等同于
var f = function(num1,num2){
return num1 + num2;
}
// 箭头函数的代码块部分多于一条语句就需要使用大括号将它们括起来
var f = (num1,num2){
return num1 + num2;
}
// 由于大括号解释为代码块,所以如果箭头函数直接返回一个对象,则必须在对象外面加上括号
var f = id=>({name:"知数SEO"});