基础函数及一些常用的函数方法2

发布时间 2023-12-30 16:13:30作者: 奇迹会出现

1.递归函数

在JavaScript中,函数直接或间接的调用自己,则该函数便称为递归函数。

 

function fn(){            //定义函数fn
    console.log(1);        //在控制台打印输出1
    fn();                //调用函数本身
}
fn();                    //调用函数

 

上述代码是一个典型的死递归,当在外部调用函数fn时,会先打印数字1,然后再次调用函数,再打印1…最终陷入永无止境的循环之中,如果电脑配置不好的,甚至可能导致死机。

 下面的代码是一段简单的累加递归函数

function add(n) {
  // 传递进来的是 5
  // 当 n === 1 的时候要结束
  if (n === 1) {
    return 1;
  }
}
add(5)

2.纯函数

纯函数的定义:

1.确定的输入,一定会产生确定的输出;

var names = ["abc", "cba", "nba", "dna"]

// slice只要给它传入一个start/end, 那么对于同一个数组来说, 它会给我们返回确定的值
// slice函数本身它是不会修改原来的数组
// slice -> this
// slice函数本身就是一个纯函数
// var newNames1 = names.slice(0, 3)
// console.log(newNames1)
// console.log(names)

// ["abc", "cba", "nba", "dna"]
// splice在执行时, 有修改掉调用的数组对象本身, 修改的这个操作就是产生的副作用
// splice不是一个纯函数
var newNames2 = names.splice(2)
console.log(newNames2)// ['nba', 'dna']
console.log(names)//(2) ['abc', 'cba']

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var newFruits = fruits.splice(2, 1, "Lemon", "Kiwi");
console.log(newFruits);//['Apple']
console.log(fruits);//['Banana', 'Orange', 'Lemon', 'Kiwi', 'Mango']

//splice() 方法向/从数组添加/删除项目,并返回删除的项目。

 

2.函数在执行过程中,不能产生副作用;

const counter = { x: 1 }
const foo = (obj, b) => {
  obj.x = 2
  return obj.x + b
}

foo(counter, 2) // => 4
counter.x // => 2

执行 foo 函数时,有将作为参数传进来的外部变量 counter.x 的值修改为 2。无论函数在哪里执行,都会修改函数外部变量的值,所以它产生了 副作用,不是 纯函数 。

3.自执行函数

自执行函数也叫立执行函数,是将函数的声明和调用合并在一起

意义:自执行函数是为了封装,不需要将普通的函数特意换成自执行函数的写法

自执行函数的第一种写法

;(function () {
               //代码块
            })()
               //解析
               //第一步 
               //先写两个()
               () ()
               //第一个()可以这样想
               1 + 1 * 3  //我想先执行 1 + 1
               (1 + 1) * 3 //这样就实现了先执行()内的
               //把函数放进()去
               (function () {})
               //第二步
               (functon () {}) ()
               第一个()//可以看作一个函数 后面这个()则是函数的执行

自执行函数的第二种写法

;(function () {
  // 代码块
}())
  //解释
  第一步 将函数放在()内
  (function () {})
  第二部 在函数的{} 后面加一个() 表示调用
  (function () {} ())
  

现在是自执行函数的传参

// 形参在function旁边的()  与普通函数一样
;(function (x,y) {
    return x + y
    //实参在最后的()中 
})(1,2)
// 形参在function旁边的()  与普通函数一样
;(function (x,y) {
    return x + y
    //实参在最后的()中   注意两种写法的括号位置是不一样的
}(1,2))

4.柯里化函数

概念:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

简单点来说就是:每次调用函数时,它只接受一部分参数,并返回一个函数,直到传递所有参数为止。
 
// 等待我们柯里化实现的方法add
function add(a, b, c, d) {
    return a + b + c + d;
};
// 最简单地实现函数add的柯里化
// 有点low,有助于理解
function add(a, b, c, d) {
    return function(a) {
        return function(b) {
            return function(c) {
                return a + b + c + d;
            }
        }
    }
}

5.闭包

换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。

function init() {
  var name = "Mozilla"; // name 是一个被 init 创建的局部变量
  function displayName() {
    // displayName() 是内部函数,一个闭包
    alert(name); // 使用了父函数中声明的变量
  }
  displayName();
}
init();
function makeAdder(x) {
  return function (y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2)); // 7
console.log(add10(2)); // 12

add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境。在 add5 的环境中,x 为 5。而在 add10 中,x 则为 10。

6.this

(1)this永远指向一个对象;(2)this的指向完全取决于函数调用的位置;

 

const test = {
  prop: 42,
  func: function () {
    return this.prop;
  },
};

console.log(test.func());
// Expected output: 42

在上述代码中,在函数内部,this 的值取决于函数如何被调用,以将 this 看作是函数的一个隐藏参数(就像函数定义中声明的参数一样),this 是语言在函数体被执行时为你创建的绑定

对于典型的函数,this 的值是函数被访问的对象。换句话说,如果函数调用的形式是 obj.f(),那么 this 就指向 obj

function getThis() {
  return this;
}

const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };

obj1.getThis = getThis;
obj2.getThis = getThis;

console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] }
console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] }