函数:就是将一些功能或语句进行封装,在需要的时候,通过调用的形式,执行这些语句。
函数也是一个对象
使用typeof
检查一个函数对象时,会返回function
<script>
// 1.申明
function foo() {
//to do something
}
// 2.调用
foo();
</script>
// 1.申明
var fn = function () {
// to do something
}
// 2.调用
fn();
<script>
function foo() {
console.log(‘小艾‘);
// 此时调用成功,原因是foo执行的时候将foo2压栈,这个时候foo2已然是个函数了
②foo2();
}
// 表达式声明的时候,只能在声明函数的后面调用
// ①foo2();
var foo2 = function () {
console.log(‘同学‘);//foo2 is not a function
}
// 申明变量调用时,在script标签中的任何位置调用都可以
foo();
</script>
原理分析:
//上面代码预解析
function foo(){}
var foo2 = undefined
foo2 = function(){}
foo()
当在①的情况下,函数寒没有赋值给foo2,此时foo2还是undefined,所以调用foo2的时候会报错。
当在②的情况下,函数foo()调用时,foo2已经赋值完毕,可以正常调用
太没有可读性了!不建议使用
//3.申明
var fn2 = new Function(‘形参1‘, ‘形参2‘, ‘函数体‘)
// 调用
fn2(实参);
函数名()
将函数转为表达式,再在后面跟一个括号,就可以自己调用自己了~
// 转为表达式:(), +, ~, -
(function foo() {
console.log(‘小艾同学‘);
})();
~ function foo2() {
console.log(‘小艾同学1‘);
}();
+function foo3() {
console.log(‘小艾同学2‘);
}();
形式上的参数。定义函数时传递的参数,当时并不知道是什么值,只是用来占位。
形参本质上是一个局部变量。
实际上的参数。调用函数时传递的参数,实参将会传递给函数中对应的形参。
<script>
function foo(a, b) {
console.log(arguments);//函数自带的属性,函数调用时传入的所有的实参的集合,是一个伪数组
return a + b;
}
var a = foo();
console.log(a);//NaN不传实参
var b = foo(1);
console.log(b);//实参少于形参,会多出来的的形参默认值是undefined,进行运算返回的是NaN
var c = foo(1, 2, 3, 4, 5, 6)
console.log(c);//实参多余形参,只取跟形参对等个数的实参参与逻辑,多出来的不会丢失,所有的实参都会存入arguments
</script>
当函数运行的结果需要在其他地方使用时,就要返回值。
<script>
function fn() {
console.log(‘小艾‘);
return;//返回值后面没有内容也是返回undefined
}
// 没有return,默认返回undefined
console.log(fn());//undefined
function foo() {
console.log(‘小艾‘);
return 666;
console.log(‘同学‘);//return后面的代码不会执行
}
console.log(foo());
function getMax() {
// return只能返回一个值,如果用,连接多个,只会返回最后面那个值
// return Math.max(...arguments), Math.min(...arguments); //返回5
// 如果要返回福讴歌,可以返回一个数组
return [Math.max(...arguments), Math.min(...arguments)];//返回[999,5]
}
var res = getMax(5, 6, 8, 999);
console.log(res);
</script>
arguments是js的一个内置函数,只要函数调用,就会自动生成一个arguments
不确定有多少个参数传递的时候,可以用 arguments 来获取
作用域是一个变量或函数的作用范围。作用域在函数定义时,就已经确定了。
当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(就近原则)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错。
var i = 1//最后来全局找
function a(){
var i = 2
//再来它最近的父级找
function b(){
i++//先在内部找
console.log(i)//3
}
b()
}
a()
函数的形参是局部变量
<script>
function foo(a) {
return a + 6;
}
var res = foo(1);
console.log(res);//7
// 函数的形参是一个局部变量,全局中无法访问
console.log(a);// a is not defined
</script>
js中没有块级作用域
<script>
// js中没有块级作用域
if (true) {
var num = 123;
console.log(num); //123
}
console.log(num); //123(可以正常打印)
// 全局变量和局部变量仅存在函数中
function fn() {
var num1 = 123;
console.log(num1);
}
console.log(num1);//num1 is not defined
</script>
js函数调用栈
<script>
function a(){
console.log(‘a‘)
}
function b(){
console.log(‘b‘)
// 函数内部的代码还是按顺序执行的,遇到新的函数执行才会进行压栈操作
a()
console.log(‘b1‘)
}
function c(){
console.log(‘c‘)
b()
console.log(‘c1‘)
}
// 在函数执行的时候会将该函数压入到执行栈里面,当函数代码执行的时候又遇到了函数执行语句,那么当前函数执行
// 上下文暂停,将新函数压入栈中...当函数执行完毕以后会发生出栈操作,函数的执行上下文交回给紧挨着
// 它的底下的函数
c() // c b a b1 c1
js中没有动态作用域,是词法作用域
<script>
// js的作用域是词法作用域/静态作用域,而不是动态作用域!!!!
// 函数作用域的形成是在函数声明的时候就决定好了的,而不是在调用的时候
var i = 0
function a(){
console.log(i)
}
function b(){
var i = 1
a() // 0
}
b()
</script>
原文:https://www.cnblogs.com/xiaoaitongxue/p/12748282.html