1. 定义函数的三种方式
1. 定义命名函数
function functionName(parameter-list) { statements }
注意: 给予函数提升的特性, 在同一个script标签内允许我们先调用函数, 再定义函数, 但是在不同的script标签内, 必须先定义, 再调用
2. 定义匿名函数
<script> var f = function(name) { document.writeln('匿名函数<br>'); document.writeln('你好' + name); }; f('zhangjian') </script>
定义匿名函数无需指定函数名, 而是将参数列表紧跟function关键字, 在函数定义语法的最后不要忘记紧跟分号
3. 使用Function类定义匿名函数
<script> var f = new Function('name' , "document.writeln('Function定义的函数<br>');" + "document.writeln('你好' + name)" ); f('zhangjian') </script>
js提供了一个Function类,该类也可以用来定义函数,FFunction类的构造器的参数个数可以不受限制, Function可以接受一系列的字符串参数,其中最后一个字符串参数是函数的执行体,z执行体的语句用分好隔开,而前面的各字符串则是函数的参数
2. 递归函数
递归函数是啥这里就不多说了哈, 不了解的可以去力扣看一下
用递归实现求n的阶乘
<script> var f = function(n) { if(typeof(n) == 'number') { if(n==1) { return 1 } else { return n * f(n-1) } } } document.write(f(4)) </script>
3. 局部变量和局部函数
在函数内用var定义的变量成为局部变量
在函数外不或者函数内不适用var定义的变量成为全局变量
如果局部变量和全局变量的变量名相同, 则局部变量会覆盖全局变量
局部函数与局部变量概念相似, 局部函数在函数里边定义
<script> function outer() { function inner1() { document.write('局部函数1') } function inner2() { document.write('拒不函数2') } inner1(); inner2(); } outer() </script>
4.函数, 方法, 对象, 变量, 类
定义一个函数后:
函数 : 这个函数可以被调用
对象:定义一个函数后,系统会创建一个对象,z这个对象是Function类的实例
方法 : 定义一个函数时,该函数通常都会附加给某个对象,作为该对象的方法
变量:在定义函数的同时,也会得到一个变量
类:在定义函数的同时,也得到了一个与函数同名的类
//判断函数是否为Function或者Object的实例
<script> var hello = function(name) { return name + '你好'; }; //判断函数是否为Function的实例, 是否为object的实例 alert((hello instanceof Function) + ' ' + (hello instanceof Object));
// 直接输出函数名, 会将函数内容全部打印
alert(hello)
//直接调用函数, 将返回函数return的值
alert(hello('zhangjian'))
//通过new关键字调用函数,通过这种方式调用总有一个返回值,返回值就是一个js对象
var obj = new hello('zhangjian');
</script>
函数的两种调用方式:
1.直接调用该函数,得到的就是该函数的返回值
2.使用new关键字来调用该函数,也就是将该函数当成类来使用,所以得到一个对象
来看一下new的使用方法:
<script> let Person = function(name, age) { // 将name赋值给name属性, age赋值给age属性 this.name = name; this.age = age; // 给类添加info方法, 通过匿名函数的方式添加 this.info = function() { document.write('my name is ' + this.name + '<br>'); document.write('im ' + this.age + 'years old'); }; }; let p = new Person('zhangjian', 16); p.info() </script>
5. 函数的实例属性和类属性
函数中的变量分为三种
- 局部变量 : 在函数中以var声明的变量
- 实例属性 : 在函数中以this前缀修饰的变量
- 类属性 : 在函数中以函数名前缀修饰的变量
实例属性是属于对象的, 因此要用对象来访问
类属性是属于类的,y因此要用类(也就是这个函数)来访问
6. 调用函数的三种方
- 直接调用函数
- 以call方法调用函数
- 以apply方法调用函数
7. 函数的独立性
虽然函数定义的时候可以定义成某个类的方法或者某个对象的方法, 但是js函数永远是独立的, 函数永远不会从属于其他类, 对象.
<script> //定义一个each函数 function Person(name) { this.name = name; this.info = function() { alert(this.name) } } //实例化一个对象p var p = new Person('bobo'); p.info() var name = 'zhangjian'; p.info.call(window); </script>
虽然程序实在Person里边定义的info函数, 但js函数永远是独立的, 我们只需要通过p.info拿到这个函数的引用, 就可以指定调用者, 调用这个函数
8. 函数提升
- 在同一个script标签内, 允许先调用函数, 再定义函数, 因为函数定义会被提升到标签顶部
- 如果使用程序先定义匿名函数, 然后将匿名函数赋值给变量, 此时提升的只有被赋值的变量, 函数定义本身不会被提升.
- 局部函数会被提升到所在函数的顶部
9. 箭头函数
<script> var arr = ['python', 'java', 'php']; var newarr = arr.map(function(ele) { return ele.length; } ); var newwarr = arr.map((ele) => { return ele.length}); // 当参数只有一个的时候, 可以省略圆括号, 当函数语句只有一个的时候, 可以省略花括号和 return // var newwarr = arr.map(ele => ele.length); document.write(newwarr) </script>
10. 函数参数的处理
基本数据类型, 值传递, 在函数内部改变该值并不会影响函数外边的值
复合数据类型, 可以理解为引用传递