js--函数(重点)

124 阅读3分钟

1.声明

1. function aa() {} //function命令
2.var aa = function() {} //函数表达式
3.构造函数:var add = new Function(
      'x',
      'y',
      'return x + y'
    );

    // 等同于
    function add(x, y) {
      return x + y;
    }
第三种特别不直观,所以几乎无人使用

如果一个函数多次声明,那么后面的就会覆盖前面的

2.递归

函数可以调用自身,这就是递归

3.第一等公民

JS语言把函数看作一种值,与其他值(字符串,数值,布尔等等地位相同),凡是可以使用值的地方,都可以使用函数。

比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处

由于函数与其他数据类型地位平等,所以在 JavaScript 语言中又称函数为第一等公民

4.函数名的提升

JavaScript 引擎将函数名视同变量名,所以使用 function 命令声明函数时,整个函数会像变量声明一样,被提升到代码头部; 所以下面代码不会报错

f();

function f() {}

但是采用赋值语句定义函数就会报错

f();
var f = function (){};
// TypeError: undefined is not a function

以上代码等同于

var f;
f();
f = function () {};

5.函数的属性和方法

name

返回函数的名字

function f1() {}
f1.name // "f1"
var f2 = function () {};
f2.name // "f2"
var f3 = function myName() {};
f3.name // 'myName'

length

获取函数的参数个数

函数的length属性与实际传入的参数个数无关,只反映函数预期传入的参数个数。

function f(a, b) {}
f.length // 2

toString()

返回一个字符串,内容是函数的源码

unction f() {
  a();
  b();
  c();
}

f.toString()
// function f() {
//  a();
//  b();
//  c();
// }

6.函数的作用域

  • 作用域:变量存在的范围
    ES5中,Javascript只有两种作用域:
    1.全局作用域,变量在整个程序中一直存在,所有地方都可以读取;
    2.函数作用域,变量只在函数内部存在。
    ES6中新增了块级作用域
    函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。
    函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)。
    函数内部定义的变量,会在该作用域内覆盖同名全局变量

7. 函数内部的变量提升

与全局作用域一样,函数作用域内部也会出现“变量提升”现象,var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部

8.函数本身的作用域

函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。

9.传递方式

  • 函数参数如果是原始类型的值(数值,字符串,布尔值),传递方式是传值传递。这意味着在函数体内部修改参数值,不会影响到函数外部;
  • 如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。
    var obj = { p: 1 };
    
    function f(o) {
      o.p = 2;
    }
    f(obj);
    
    obj.p // 2
    

注意,如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。

    var obj = [1, 2, 3];
    
    function f(o) {
      o = [2, 3, 4];
    }
    f(obj);
    
    obj // [1, 2, 3]
上面代码中,在函数f内部,参数对象obj被整个替换成另一个值。这时不会影响到原始值。
这是因为,形式参数(o)的值实际是参数obj的地
址,重新对o赋值导致o指向另一个地址,保存在原地址上的值当然不受影响。
(可以自己画一下内存图)