Day 7
函数
将一些功能或语句进行封装,在需要的时候调用来执行这些语句,特别是重复的
作用:
- 避免重复劳动
- 模块化
例如写一个从1加到N求和的函数
// 封装函数
function addN(n){
var sum = 0
for(var i = 0;i <= n;i++){
sum += 1
}
console.log(sum)
}
函数是一个对象,是一个函数对象,用typeof来看返回一个function
函数定义/声明
-
方式一、使用函数声明来创建一个函数
-
function 变量名(参数){
代码}
- 如果没有名字如何调用?会报错,必须要有名字。
- *除非声明之后立即调用(也即立即执行函数/匿名函数)
- 如果没有名字如何调用?会报错,必须要有名字。
-
-
方式二、使用函数表达式来创建
- 匿名函数(没有函数名称)
var addN = function(){
代码
}
-
关于匿名函数看后面。
-
方式一与方式二这两种有什么区别?
-
变量的声明提升。
console.log(fn) //虽然是写在前面 var fn = function(){ // 但是这里会进行变量的声明提前 console.log(123) } function fn(){ // 这里将整个函数提升到最前面 console.log(777) } -
方式一直接将整个函数声明,但是是提升到最前面
-
方式二也会声明提升,但不会进行赋值
-
如果同时写两个方式,那么只会是方式一的
-
变量的作用域(Scope)
作用域有两个:全局作用域和函数作用域。也即变量生效的范围
- 直接写在script标签中的js代码,都在全局作用域。
- 全局作用域在页面打开是创建,关闭时销毁
- 不在函数内声明的变量,都是全局变量。
- 所有的全局变量都会放在window的属性中。
- window代表的是一个浏览器的窗口,由浏览器创建(不用我们创建)且我们可以直接使用
- 所有的全局变量都会放在window的属性中。
- 在全局作用域中:
- 创建的变量都会作为window对象的属性保存。
- 创建的函数都会作为window对象的方法保存。
- 函数作用域是可以访问到全局变量的
- 局部作用域(函数作用域)
- 在函数中声明一个变量var = 变量,再函数外输出这个变量是没用的。
- 全局作用域无法访问到函数作用域的变量
- 在函数中声明,只在函数中有效。
- 但如果没有声明var,而是直接变量 = 值,那么会自动声明成全局变量。
- 在函数中声明一个变量var = 变量,再函数外输出这个变量是没用的。
执行期上下文
变量在用完(函数执行完)之后是会再内存中被销毁的。
- 那么如何保留变量不被销毁?(执行期上下文被销毁的例外情况)
- 某函数的变量被另一个函数外部引用的时候,就不会在函数执行完毕后销毁
定义形参,其实就是在函数作用域中声明了变量
函数的参数
-
形式参数(形参),声明里的参数
-
实际参数(实参),实际调用的参数。形参相对于实参来说的。
-
注意:JS中不会对实际传入的参数检测,
- 实际调用的时候,可以传部分值,也可以不传值,还可以传超过声明的值
- 不传值可能会undefined
- 多传值,也不会报错,多余的没啥用
- 实际调用的时候,可以传部分值,也可以不传值,还可以传超过声明的值
-
如果不知道你传多少个值,但又想都起作用(比如把你传的参数都加起来),可以用arguments
-
arguments。用来获取所有实际传递的参数
-
function add(){ console.log(arguments) for(var i = 0;i<arguments.length;i++){ sum = sum + arguments[i] } } add(1,2,3,4,999)
-
函数的返回值
注意return和console.log的区别
return和console。log,没有一点关系
return的意思是:
-
return后面的值,会作为最终的结果返回
-
可以定义一个变量来接收
-
function add(){ console.log(arguments) for(var i = 0;i<arguments.length;i++){ sum = sum + arguments[i] } } var result = add(1,2,3,4,999)//定义变量接收 comsole.log(result)
-
-
结束方法
- return后面的语句都不会执行
-
如果return后不跟任何值,则默认返回undefined
-
如果不写return的话也默认返回undefined
-
返回值可以是任何的数据类型,甚至还可以是一个函数
-
<script type="text/javascript"> function add(a,b){ var outResult = function(){ return a+b; } return outResult //返回函数 } var a = add(3,4) console.log(a) // 输出变量(是一个函数) console.log(a()); //输出函数值 </script> -
<script type="text/javascript"> function add(a,b){ var outResult = function(){ return a+b; } return outResult() //返回函数值 } var a = add(3,4) console.log(a) // 输出变量(函数值) </script>
-
函数名、函数体和函数加载问题
- 函数名 == 函数整体
- 不加括号的函数(可以见上一小节最后两个js的对比
- fn():调用函数。相当于获取函数返回值
- fn:函数对象。相当于直接获取整个函数对象、
- 例如直接console。log(函数名称)
- js加载的时候只加载函数名而不加载函数体。若要使用内部的变量,则需要调用函数。
立即执行函数
现有匿名函数如下:
function(a, b) {
console.log("a = " + a);
console.log("b = " + b);
};
立即执行函数如下:(也即加括号)
(function(a, b) {
console.log("a = " + a);
console.log("b = " + b);
})(123, 456); //一定要注意分号
- 为什么需要这种立即执行函数呢?
- 不会创建全局作用域
- 多人合作写代码的时候,变量名称重复的时候是不会报错的,那怎么找BUG呢?就用匿名函数,并且只在函数中声明,也即局部变量