4 - 函数基础与种类、形实参及映射、变量类型

207 阅读3分钟

一、函数基础与种类

1. 函数基础:

  • 函数作用:功能的封装、解耦合。
  • 函数名命名和变量名规则相同:
a.  不能以数字开头
b.  以字母、$、_开头
c.  不能使用关键字、保留字
d.  语义化、结构化命名
e.  小驼峰命名法:myName()

2. 函数的种类:

  • 可以使用 Function 构造函数和一个函数声明来定义函数
  • 函数内部可用return语句终止函数执行,返回对应的值

函数声明:

/**
* 1. 函数声明:
* 预编译的时候,函数声明会提升,所以函数调用在函数声明前后调用都可以
*/

// 1. 在函数声明前调用:函数声明提升-> function test(){...} -> test();
// test(); 
function test(){
  console.log("函数声明");
}
// 2. 在函数声明后调用
test();

函数表达式:

/**
* 2. 函数表达式:
* 预编译的时候,函数表达式不会提升,所以函数调用要放在函数表达式之后,不然会报错
*/

// test1(); //在函数表达式前面调用函数,报错:Uncaught TypeError: test1 is not a function

var test1 = function test(){
  return '函数表达式'
}

test1(); //"函数表达式"

二、 形实参及映射

1. 形实参:

  • 形参:函数定义里面的参数;
  • 实参:函数调用时传入的参数;
  • 形式参个数可以不相等;
  • 可以在函数内部修改传入的实参值;
  • 实参中未传入值,在函数内部中给形参赋值是无效的,因为给未定义的形参赋值,是undefined;
  • 如果形参跟实参是对应关系,那么改变形参的值,实参的值也会跟着改变,它们之间存在映射关系;
function test(a, b, c) { //形参 -> 3个
  a = 3;
  c = 5;
  //arguments[0] <-> a ,形参a重新被赋值为3,所以实参arguments[0]也会跟着改变
  console.log(arguments[0]); // 3 
  
  //因为实参只有2个,1跟2(arguments[0]、arguments[1]),所以arguments[2]是不存在的
  //给未定义的值赋值是undefined
  console.log(arguments[2]); // undefined
}

test(1, 2);  // 实参arguments: arguments[0] = 1 ; arguments[1] = 2

2. demo:根据输入的实参值,求它们的累加和

function sum() {
  var sum = 0;
  var _argsLength = arguments.length; // 实参的长度
  for (var i = 0; i < _argsLength; i++) {
    var idx = arguments[i];
    sum += idx;
  }
  console.log(sum); // 4+5+6=15
}

sum(4, 5, 6)

三、变量类型

1. 全局变量var

  • 在全局环境下声明的变量在任何地方都可以访问。
  • 在函数内定义变量时省略var操作符,可以创建一个全局变量。只要调用该函数,就会定义这个变量,并且可以在函数外部访问到。

2. 局部变量

  • 在函数内部使用var声明变量,它会成为函数的内部变量,该变量在函数执行完后就会销毁。
// 全局变量
a = 1;
function test() {
  // 局部变量
  var b = 2;
  console.log(a, b);  // 1 2
  // 重新赋值全局变量a    a -> 4
  a = 4;
  function test1() {
    // 局部变量
    var c = 3;
    // 重新赋值test1内的变量b   b -> 5
    b = 5;
    console.log(b);   // 5
  }
  test1();
  // test1函数运行完时局部变量c被销毁,所以在外部访问c会报错
  console.log(c); // Uncaught ReferenceError: c is not defined
}
test();

四、demo:

4.1 定义一个函数,从window.prompt接收一个饮料的名称,函数返回对应的价格

function drink(name) {
  switch (name) {
    case '橙汁':
      return '¥5';
      break;
    case '可乐':
      return '¥3';
      break;
    case '雪碧':
      return '¥3';
      break;
  }
}
var name = window.prompt("请输入饮料的名称");
drink(name);

4.2 定义一个函数,从window.prompt接收第一个数,然后一个运算符号(+ - * / %),最后接收第二个数,利用这个函数做运算,并返回运算结果

function compute(value1, type, value2) {
  switch (type) {
    case '+':
      return value1 + value2;
      break;
    case '-':
      return value1 - value2;
      break;
    case '*':
      return value1 * value2;
      break;
    case '/':
      return value1 / value2;
      break;
    case '%':
      return value1 % value2;
      break;
    default:
      console.log('输入格式错误');
  }
}
var value1 = Number(window.prompt('请输入第一个数字'));
var type = window.prompt('请输入运算符');
var value2 = Number(window.prompt('请输入第二个数字'));
compute(value1, type, value2);

4.3 定义一个函数,从window.prompt接收一个n,算出n的阶乘,不能用for循环

/**
  *  !: 阶乘
  *  n! = n * (n-1)!
  */
function fact(n) {
  if (n === 1) {
    return 1;
  }
  return n * fact(n - 1);
}
fact(5);

4.4 定义一个函数,从window.prompt接收一个n,算出斐波那契数列的第n项,不能用for循环

// 递归写法
// 递归:递归总是走到出口的时候,再一步一步向上赋值后返回结果,
// 递归的两个因素:1.找到计算的规律;2.找到出口,让这个递归函数可以结束。
/** 第n的值:n = (n-1) + (n-2) -> 例如第3位: 2 = 1 + 1
  *  规律:第1/2位都是1,第3位开始,是它的前两位相加的和,3->2 4->3 5->5...以此类推
  *  算出斐波那契数列的第n位:1   1   2   3   5  8   13   21 ...
  *                         n1  n2  n3
  *                             n1  n2  n3
  *                                 n1  n2  n3
  */
function test(n) {
  if (n <= 0) {
    return 0;
  }
  if (n <= 2) {
    return 1;
  } else {
    return test(n - 1) + test(n - 2);
  }
}
var n = parseInt(window.prompt('请输入一个正整数'));
console.log(test(n));