JS的函数function
一.JS函数的简介
函数(function):
- 函数也是一个对象
- 函数中封装了一些功能(代码), 在需要时可以执行这些功能(代码)
- 封装到函数的代码不会立即执行, 只有调用时才会执行
- 调用函数时代码顺序执行, 调用语法: 函数对象()
- 使用typeof检查一个函数对象时, 会返回function
A.创建一个函数对象
- 将要封装的代码以字符串形式传递给构造函数, 例:
1 | var fun = new Function("console.log('这是我的第一个函数~~~')"); |
- 使用函数声明来船舰一个函数(对象), 格式:
1 | function 函数名([形参1,形参2,形参3,...,形参n]){ |
- 使用函数表达式创建一个函数, 格式:
1 | var 函数名 = function([形参1,形参2,形参3,...,形参n]){ |
B.参数
- 在函数的()中, 可以指定0个或多个形参
- 多个形参之间用逗号隔开, 声明了形参就相当于在函数内部声明了对应的变量
- 声明的形参并没有被赋值
- 调用函数时, 可以在()中指定实参, 实参的值会依次赋值给形参
- 调用函数时, 解析器不会检查形参与实参的数量是否匹配
- 函数的实参可以是任何类型的值, 包括基本类型、对象、函数(对象).
特别注意: 调用函数时, 解析器也不会检查实参的类型, 所以要检查一下参数是否合法
例题: 定义一个能求两个数和的函数
1 | function sum(a,b){ |
C.返回值
- 在函数中, 可以用return关键字返回一个表达式的值
- 可以在调用函数处, 声明一个变量接收该函数的返回值
- 若函数中不写return或没有return一个值, 则会默认return undefined;
- return语句之后的代码不会被执行
- 函数的返回值也可以是任意类型的值, 基本类型、对象、函数
例: 定义一个能求两个数最大值的函数, 并将最大值返回.
1 | function max(a,b){ |
D.立即执行函数
- 函数定义完, 立即就会被调用
- 这种函数往往是匿名函数, 只会执行一次.例:
1 | //先用一对小括号将匿名函数括起来,表示是一个整体,否则不允许这样声明函数 |
E.方法(method)
- 一类特殊的函数, 这类函数是对象的属性
- 若一个函数成了对象的一个属性, 那这个函数就叫做对象的方法
- 调用函数就叫做调用的对象的某方法
1 | document.write("Hello");//调用document对象的write方法 |
二.作用域(Scope)
A.全局作用域
- 直接编写在script标签中的JS代码, 都在全局作用域中
- 全局作用域在页面打开时创建, 在页面关闭时销毁
- 全局作用域中有一个全局对象window, 它代表一个浏览器窗口, 由浏览器创建, 我们可以直接使用
- 全局作用域中我们创建的变量都会作为window对象的属性保存, 函数作为window的方法
- 全局作用域里的变量都是全局变量, 在页面的任何部分都能访问到
变量的声明提前: 使用var声明的变量, 会在所有的代码执行之前被声明(但不会被赋值)
但声明变量时不使用var, 则变量不会被提前声明
函数的声明提前: 使用函数声明的形式创建的函数 function 函数名(){}
会在所有代码执行前被创建, 所以我们可以在函数声明前调用它.
但是用函数表达式创建的函数 var fun = function(){};
不会被声明提前, 所以不能在声明前调用.
1 | console.log(a);//输出:undefined |
B.函数作用域
- 函数被调用时, 创建自己的函数作用域, 函数执行完毕, 函数作用域销毁
- 每调用一次函数, 创建一个新的函数作用域, 作用域之间互相独立
- 函数作用域中可以访问到全局变量, 但全局作用域无法访问到局部变量
- 在函数中操作一个变量时, 首先在自身作用域中寻找, 没有的话向上一级寻找
- 函数中想使用全局变量, 可以使用window.变量名
- 函数的形参相当于在函数作用域中声明的.
也存在声明提前的问题, 但提前声明于当前作用域
三.debug
这种调试, 可以查看执行过程中内存的状态, 各变变量的情况.
1 | alert(d);//声明提前 |
先打开, 浏览器的开发者工具, 以chrome为例, 按F12, 选择sources, 之后如下图:
其他浏览器类似
四.this
你可以这样理解:
解析器在调用函数时每次都会向函数内部传递一个隐含的参数this, this指向一个对象, 这个函数我们称为函数执行的上下文对象, 根据函数的调用方式不同, this会指向不同的对象
1 | function fun(){ |
五.call()和apply()
- 这两个方法都是函数对象的方法, 需要通过函数对象来调用
- 当函数对象调用call()和apply()方法时, 函数中的代码也会执行.
- 可以将一个对象指定为call和apply的第一个参数, 这个对象将会成为函数执行时的this
- call()方法, 将函数原本的实参在第一个参数(对象)以后依次传递给函数的形参
- apply()方法, 将函数原本的实参封装到一个数组统一传递.
1 | function fun(){ |
this的情况:
- 在函数中调用时, this永远指window
- 在方法中调用时, this是调用方法的对象
- 在构造函数中调用时, this是正在创建的对象
- 使用call和apply调用时, this是参数传递过来的对象
六.arguments
在调用函数时, 浏览器都会传递进两个隐含的参数:
①函数的上下文对象:this
②封装实参的对象: arguments, 我们传递的实参都保存在里面
- arguments是一个类数组对象, 它不是数组, 但是它也可以通过数字索引来操作数据.
- arguments.length可以获取实参的长度, 我们即使没定义形参, 也可以通过arguments来使用形参, 但这样比较麻烦
- arguments[0]表示第一个实参, 以此类推.
- arguments.callee属性, 表示当前的函数对象
1 | function fun(){ |