欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript函數(shù)和作用域(經(jīng)典面試題)

 更新時(shí)間:2025年09月16日 14:08:02   作者:meng半顆糖  
文章系統(tǒng)梳理了JavaScript中的核心函數(shù)概念,包括閉包、詞法作用域與動(dòng)態(tài)作用域的區(qū)別、call/apply/bind方法、高階函數(shù)、箭頭函數(shù)、生成器、防抖節(jié)流技術(shù)、遞歸優(yōu)缺點(diǎn)、純函數(shù)及函數(shù)重載與偏函數(shù),感興趣的朋友跟隨小編一起看看吧

一、閉包,使用場(chǎng)景

1.閉包的定義

閉包(Closure)是指函數(shù)與其引用環(huán)境(lexical environment)的組合。當(dāng)一個(gè)函數(shù)能夠記住并訪(fǎng)問(wèn)其定義時(shí)的作用域,即使該函數(shù)在其作用域外執(zhí)行,依然可以訪(fǎng)問(wèn)那些變量。閉包的核心特點(diǎn)是:

  1. 函數(shù)嵌套:閉包通常涉及嵌套函數(shù)(內(nèi)部函數(shù)引用外部函數(shù)的變量)。
  2. 變量持久化:外部函數(shù)的變量不會(huì)被垃圾回收,因?yàn)閮?nèi)部函數(shù)仍持有引用。

2.閉包的實(shí)現(xiàn)原理

function outer() {
    let count = 0;
    function inner() {
        count++;
        console.log(count);
    }
    return inner;
}
const closureFunc = outer();
closureFunc(); // 輸出 1
closureFunc(); // 輸出 2
  • inner 函數(shù)引用了 outer 的變量 count,形成閉包。
  • 每次調(diào)用 closureFunc 時(shí),count 的值會(huì)被保留。

3.閉包的應(yīng)用場(chǎng)景

(1)數(shù)據(jù)封裝與私有變量

通過(guò)閉包模擬私有變量,避免全局污染:

function createCounter() {
    let privateCount = 0;
    return {
        increment: function() { privateCount++; },
        getValue: function() { return privateCount; }
    };
}
const counter = createCounter();
counter.increment();
console.log(counter.getValue()); // 輸出 1

(2)函數(shù)柯里化

將多參數(shù)函數(shù)轉(zhuǎn)換為單參數(shù)鏈?zhǔn)秸{(diào)用:

function multiply(a) {
    return function(b) {
        return a * b;
    };
}
const double = multiply(2);
console.log(double(5)); // 輸出 10

(3)事件處理與回調(diào)

在異步操作中保留上下文:

function setupClickHandler() {
    let clicked = 0;
    document.getElementById('btn').addEventListener('click', function() {
        clicked++;
        console.log(`按鈕被點(diǎn)擊 ${clicked} 次`);
    });
}
setupClickHandler();

(4)模塊化開(kāi)發(fā)

實(shí)現(xiàn)模塊的隔離作用域:

const module = (function() {
    let privateData = '秘密';
    return {
        getData: function() { return privateData; }
    };
})();
console.log(module.getData()); // 輸出 "秘密"

4.注意事項(xiàng)

  1. 內(nèi)存泄漏:閉包可能導(dǎo)致變量長(zhǎng)期駐留內(nèi)存,需手動(dòng)解除引用(如 closureFunc = null)。
  2. 性能影響:過(guò)度使用閉包會(huì)增加內(nèi)存消耗。

二、詞法作用域和動(dòng)態(tài)作用域區(qū)別

1.詞法作用域(Lexical Scoping)

詞法作用域由代碼書(shū)寫(xiě)時(shí)的結(jié)構(gòu)決定,作用域在代碼編譯階段就已確定。變量的訪(fǎng)問(wèn)權(quán)限取決于其在代碼中的物理位置(即定義時(shí)的嵌套關(guān)系),與函數(shù)調(diào)用時(shí)的執(zhí)行上下文無(wú)關(guān)。

  • 特點(diǎn)
    • 作用域鏈基于函數(shù)或塊的定義位置建立,內(nèi)部函數(shù)可訪(fǎng)問(wèn)外部函數(shù)的變量,但外部函數(shù)無(wú)法訪(fǎng)問(wèn)內(nèi)部函數(shù)的變量。
    • 大多數(shù)現(xiàn)代編程語(yǔ)言(如JavaScript、Python、C++)默認(rèn)采用詞法作用域。
  • 示例
function outer() {
  let x = 10;
  function inner() {
    console.log(x); // 訪(fǎng)問(wèn)外部函數(shù)的x(詞法作用域)
  }
  inner();
}
outer(); // 輸出10

2.動(dòng)態(tài)作用域(Dynamic Scoping)

動(dòng)態(tài)作用域由函數(shù)調(diào)用時(shí)的執(zhí)行上下文決定,作用域鏈在運(yùn)行時(shí)動(dòng)態(tài)生成。變量的訪(fǎng)問(wèn)權(quán)限取決于調(diào)用鏈的順序,而非代碼的靜態(tài)結(jié)構(gòu)。

  • 特點(diǎn)
    • 函數(shù)內(nèi)部的變量可能因調(diào)用方式不同而引用不同的值。
    • 傳統(tǒng)語(yǔ)言如Bash、Perl的局部變量支持動(dòng)態(tài)作用域,但現(xiàn)代語(yǔ)言較少使用。
  • 示例
x=1
function foo() {
  echo $x # 動(dòng)態(tài)作用域下,x的值取決于調(diào)用者
}
function bar() {
  local x=2
  foo
}
bar # 輸出2(動(dòng)態(tài)作用域)

3.核心區(qū)別

  • 確定時(shí)機(jī)
    • 詞法作用域在代碼編譯時(shí)靜態(tài)確定。
    • 動(dòng)態(tài)作用域在函數(shù)運(yùn)行時(shí)動(dòng)態(tài)確定。
  • 依賴(lài)關(guān)系
    • 詞法作用域依賴(lài)代碼的物理結(jié)構(gòu)(嵌套關(guān)系)。
    • 動(dòng)態(tài)作用域依賴(lài)函數(shù)的調(diào)用棧。
  • 典型語(yǔ)言
    • 詞法作用域:JavaScript、Python、C。
    • 動(dòng)態(tài)作用域:Bash、Emacs Lisp(部分支持)。
  • 性能影響
    • 詞法作用域允許更高效的靜態(tài)優(yōu)化。
    • 動(dòng)態(tài)作用域需在運(yùn)行時(shí)解析變量,可能降低性能。

4.實(shí)際影響

  • 閉包(Closure):詞法作用域是閉包的基礎(chǔ),內(nèi)部函數(shù)可“記住”定義時(shí)的環(huán)境。
  • 調(diào)試難度:動(dòng)態(tài)作用域可能導(dǎo)致變量值難以預(yù)測(cè),增加調(diào)試復(fù)雜度。

三、call、apply和bind方法的區(qū)別

1.功能:

這三個(gè)方法都是 JavaScript 中函數(shù)對(duì)象的方法,用于顯式綁定函數(shù)的 this 值,并執(zhí)行函數(shù)。核心功能是動(dòng)態(tài)改變函數(shù)運(yùn)行時(shí) this 的指向。

2.call 方法

  • 語(yǔ)法: func.call(thisArg, arg1, arg2, ...)
  • 作用: 立即調(diào)用函數(shù),并指定函數(shù)內(nèi)部的 this 值為 thisArg,同時(shí)傳遞參數(shù)列表(逐個(gè)傳遞)。
  • 示例:
function greet(name) {
  console.log(`Hello, ${name}! I'm ${this.title}.`);
}
const context = { title: 'Mr' };
greet.call(context, 'Alice'); // 輸出: Hello, Alice! I'm Mr.

3.apply 方法

  • 語(yǔ)法: func.apply(thisArg, [argsArray])
  • 作用: 立即調(diào)用函數(shù),并指定 this 值為 thisArg,參數(shù)通過(guò)數(shù)組(或類(lèi)數(shù)組對(duì)象)傳遞。
  • 與 call 的區(qū)別: 僅參數(shù)傳遞方式不同(數(shù)組 vs 逐個(gè)參數(shù))。
  • 示例:
greet.apply(context, ['Alice']); // 輸出與 call 相同

4.bind 方法

  • 語(yǔ)法: func.bind(thisArg, arg1, arg2, ...)
  • 作用: 返回一個(gè)新函數(shù),新函數(shù)的 this 永久綁定為 thisArg,并可預(yù)先綁定部分參數(shù)(柯里化)。
  • 特點(diǎn): 不會(huì)立即執(zhí)行函數(shù),需手動(dòng)調(diào)用返回的新函數(shù)。
  • 示例:
const boundGreet = greet.bind(context, 'Alice');
boundGreet(); // 輸出: Hello, Alice! I'm Mr.

5.區(qū)別:

方法調(diào)用時(shí)機(jī)參數(shù)形式返回值
call立即執(zhí)行逐個(gè)參數(shù)函數(shù)執(zhí)行結(jié)果
apply立即執(zhí)行數(shù)組或類(lèi)數(shù)組函數(shù)執(zhí)行結(jié)果
bind延遲執(zhí)行逐個(gè)參數(shù)綁定后的函數(shù)

6.使用場(chǎng)景

  • call/apply: 需要立即調(diào)用函數(shù)并明確 this 時(shí),如借用其他對(duì)象的方法(如數(shù)組方法用于類(lèi)數(shù)組對(duì)象)。
  • bind: 需要固定 this 或部分參數(shù)時(shí)(如事件監(jiān)聽(tīng)回調(diào)、定時(shí)器函數(shù))。

示例:借用數(shù)組方法

const arrayLike = { 0: 'a', 1: 'b', length: 2 };
Array.prototype.push.call(arrayLike, 'c'); // arrayLike 變?yōu)?{ 0: 'a', 1: 'b', 2: 'c', length: 3 }

四、什么是高階函數(shù)

1.高階函數(shù)的定義

高階函數(shù)是指能夠接收其他函數(shù)作為參數(shù),或者將函數(shù)作為返回值的函數(shù)。這種特性使得代碼更具抽象性和靈活性,常用于函數(shù)式編程中。

2.高階函數(shù)的特點(diǎn)

(1)接收函數(shù)作為參數(shù)
高階函數(shù)可以接受一個(gè)或多個(gè)函數(shù)作為輸入?yún)?shù)。例如,map、filterreduce 是常見(jiàn)的高階函數(shù),它們通過(guò)傳入的函數(shù)對(duì)數(shù)據(jù)進(jìn)行處理。

(2)返回函數(shù)作為結(jié)果
高階函數(shù)可以生成并返回一個(gè)新函數(shù)。例如,閉包或裝飾器(在 Python 中)通常會(huì)返回一個(gè)函數(shù)。

3.高階函數(shù)的常見(jiàn)用例

(1)函數(shù)組合
將多個(gè)函數(shù)組合成一個(gè)新的函數(shù),例如 compose(f, g)(x) 等價(jià)于 f(g(x))。

(2)回調(diào)函數(shù)
在異步編程中,高階函數(shù)常用于處理回調(diào)邏輯,例如 setTimeout 或事件監(jiān)聽(tīng)器。

(3)裝飾器模式
在不修改原函數(shù)代碼的情況下,通過(guò)高階函數(shù)擴(kuò)展其功能。例如 Python 的 @decorator 語(yǔ)法。

4.示例

// 接收函數(shù)作為參數(shù)
const numbers = [1, 2, 3];
const squared = numbers.map(x => x * x); // [1, 4, 9]
// 返回函數(shù)
function multiplier(factor) {
  return x => x * factor;
}
const double = multiplier(2);
console.log(double(5)); // 10

5.優(yōu)勢(shì)

  • 代碼復(fù)用性:通過(guò)抽象通用邏輯,減少重復(fù)代碼。
  • 靈活性:動(dòng)態(tài)調(diào)整函數(shù)行為,適應(yīng)不同場(chǎng)景。
  • 可讀性:通過(guò)函數(shù)組合,使代碼更符合聲明式編程風(fēng)格。

五、解釋箭頭函數(shù)的特性及其與普通函數(shù)的區(qū)別

1.特性

箭頭函數(shù)(Arrow Function)是ES6引入的一種簡(jiǎn)化函數(shù)定義的語(yǔ)法,具有以下核心特性:

簡(jiǎn)潔語(yǔ)法:省略function關(guān)鍵字,使用=>定義函數(shù)。單行表達(dá)式可省略{}return。

const add = (a, b) => a + b;

無(wú)this綁定:箭頭函數(shù)不綁定自身的this,而是繼承外層作用域的this值。

const obj = {
  value: 10,
  getValue: () => console.log(this.value) // 輸出undefined(繼承全局作用域)
};

無(wú)arguments對(duì)象:需使用剩余參數(shù)(...args)替代。

const logArgs = (...args) => console.log(args);

不可作為構(gòu)造函數(shù):無(wú)法通過(guò)new調(diào)用,且沒(méi)有prototype屬性。

const Foo = () => {};
new Foo(); // TypeError: Foo is not a constructor

2.區(qū)別

(1)this綁定

普通函數(shù)的this由調(diào)用方式?jīng)Q定(動(dòng)態(tài)綁定),箭頭函數(shù)繼承定義時(shí)的this(靜態(tài)綁定)。

function regularFunc() { console.log(this); }
const arrowFunc = () => console.log(this);
const obj = { method: regularFunc, arrowMethod: arrowFunc };
obj.method();      // 輸出obj(普通函數(shù))
obj.arrowMethod(); // 輸出全局對(duì)象(箭頭函數(shù)繼承定義時(shí)的this)

(2)構(gòu)造函數(shù)與prototype

普通函數(shù)可作為構(gòu)造函數(shù),箭頭函數(shù)不能。

(3)arguments對(duì)象

普通函數(shù)可通過(guò)arguments訪(fǎng)問(wèn)參數(shù),箭頭函數(shù)需使用剩余參數(shù)。

(4)語(yǔ)法靈活性

普通函數(shù)支持函數(shù)聲明和表達(dá)式,箭頭函數(shù)僅限表達(dá)式形式。

3.適用場(chǎng)景

箭頭函數(shù):適合需要綁定外層this的場(chǎng)景(如回調(diào)函數(shù)、數(shù)組方法)。

[1, 2, 3].map(item => item * 2);

普通函數(shù):需要?jiǎng)討B(tài)this、構(gòu)造函數(shù)或arguments時(shí)使用。

function Person(name) { this.name = name; }

六、什么是生成器函數(shù)

1.概念

生成器函數(shù)是 JavaScript 中的一種特殊函數(shù),允許通過(guò) yield 關(guān)鍵字暫停和恢復(fù)執(zhí)行。它返回一個(gè)生成器對(duì)象(Generator),該對(duì)象遵循迭代器協(xié)議,可以逐步產(chǎn)生值,而非一次性計(jì)算所有結(jié)果。

2.基本語(yǔ)法

生成器函數(shù)通過(guò)在 function 后添加星號(hào)(*)定義:

function* generatorFunction() {
  yield 'value1';
  yield 'value2';
  return 'finalValue'; // 可選
}

調(diào)用生成器函數(shù)時(shí),不會(huì)立即執(zhí)行函數(shù)體,而是返回一個(gè)生成器對(duì)象:

const generator = generatorFunction();

3.核心特性

暫停與恢復(fù)
通過(guò) yield 暫停函數(shù)執(zhí)行,并返回當(dāng)前值。調(diào)用 next() 方法恢復(fù)執(zhí)行,直到下一個(gè) yieldreturn。

惰性求值
值按需生成,節(jié)省內(nèi)存。例如處理大型數(shù)據(jù)集時(shí),無(wú)需預(yù)先生成全部結(jié)果。

4.對(duì)象的方法

  • next():恢復(fù)執(zhí)行,返回 { value: yieldedValue, done: boolean }。
  • return(value):終止生成器,返回 { value: value, done: true }。
  • throw(error):向生成器拋入錯(cuò)誤,可在函數(shù)內(nèi)通過(guò) try-catch 捕獲。

示例:生成斐波那契數(shù)列

function* fibonacci() {
  let [a, b] = [0, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}
const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1

5.區(qū)別

特性生成器函數(shù)普通函數(shù)
執(zhí)行方式可暫停和恢復(fù)一次性執(zhí)行完畢
返回值生成器對(duì)象(迭代器)直接返回結(jié)果
內(nèi)存占用惰性計(jì)算,內(nèi)存效率高可能占用更多內(nèi)存

6.常見(jiàn)應(yīng)用場(chǎng)景

  • 異步編程:與 Promise 結(jié)合簡(jiǎn)化異步流程(如 redux-saga)。
  • 無(wú)限序列:按需生成無(wú)限序列(如斐波那契數(shù)列)。
  • 狀態(tài)管理:通過(guò) yield 暫停保存中間狀態(tài)。

七、防抖

1.概念

防抖(Debounce)是一種優(yōu)化高頻觸發(fā)事件的技術(shù),確保事件在停止觸發(fā)后的一段時(shí)間內(nèi)只執(zhí)行一次。常用于輸入框搜索、窗口大小調(diào)整等場(chǎng)景。

2.基礎(chǔ)實(shí)現(xiàn)

function debounce(func, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}
  • 核心邏輯:每次觸發(fā)時(shí)清除舊定時(shí)器,重新設(shè)置延遲執(zhí)行。
  • 參數(shù)說(shuō)明
    • func:需要防抖的目標(biāo)函數(shù)。
    • delay:延遲時(shí)間(毫秒)。

3.立即執(zhí)行版本

若需首次觸發(fā)立即執(zhí)行,后續(xù)延遲可添加標(biāo)志位控制:

function debounce(func, delay, immediate) {
  let timer;
  return function(...args) {
    const context = this;
    if (immediate && !timer) {
      func.apply(context, args);
    }
    clearTimeout(timer);
    timer = setTimeout(() => {
      timer = null;
      if (!immediate) {
        func.apply(context, args);
      }
    }, delay);
  };
}

immediatetrue時(shí):首次觸發(fā)立即執(zhí)行,后續(xù)停止觸發(fā)delay毫秒后再恢復(fù)立即執(zhí)行能力。

4.取消功能擴(kuò)展

為防抖函數(shù)添加取消方法:

function debounce(func, delay) {
  let timer;
  const debounced = function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
  debounced.cancel = () => {
    clearTimeout(timer);
    timer = null;
  };
  return debounced;
}

調(diào)用示例:

const debouncedFn = debounce(handler, 500);
debouncedFn.cancel(); // 取消延遲執(zhí)行

5.應(yīng)用場(chǎng)景

  1. 輸入框搜索:用戶(hù)停止輸入500毫秒后發(fā)起請(qǐng)求。
  2. 窗口調(diào)整:停止調(diào)整窗口后計(jì)算布局。
  3. 按鈕防重復(fù)點(diǎn)擊:避免用戶(hù)快速多次提交。

6.注意事項(xiàng)

  • 確保functhis指向正確,需通過(guò)applycall綁定上下文。
  • 頻繁觸發(fā)的場(chǎng)景下(如動(dòng)畫(huà)),防抖可能導(dǎo)致延遲過(guò)高,需權(quán)衡延遲時(shí)間。

八、節(jié)流

1.概念

函數(shù)節(jié)流(Throttle)是一種限制函數(shù)執(zhí)行頻率的技術(shù),確保函數(shù)在指定時(shí)間間隔內(nèi)只執(zhí)行一次。常用于高頻事件(如滾動(dòng)、輸入、窗口調(diào)整)的性能優(yōu)化。

2.時(shí)間戳版節(jié)流

通過(guò)記錄上一次執(zhí)行的時(shí)間戳,判斷當(dāng)前時(shí)間是否超過(guò)間隔:

function throttle(func, delay) {
    let lastTime = 0;
    return function(...args) {
        const now = Date.now();
        if (now - lastTime >= delay) {
            func.apply(this, args);
            lastTime = now;
        }
    };
}

特點(diǎn):立即執(zhí)行,但最后一次觸發(fā)可能不執(zhí)行。

3.定時(shí)器版節(jié)流

通過(guò)定時(shí)器控制執(zhí)行,確保間隔結(jié)束后觸發(fā):

function throttle(func, delay) {
    let timer = null;
    return function(...args) {
        if (!timer) {
            timer = setTimeout(() => {
                func.apply(this, args);
                timer = null;
            }, delay);
        }
    };
}

特點(diǎn):延遲執(zhí)行,確保最后一次觸發(fā)會(huì)執(zhí)行。

4.結(jié)合時(shí)間戳與定時(shí)器

綜合兩種方案,實(shí)現(xiàn)首次立即執(zhí)行、末次延遲執(zhí)行的效果:

function throttle(func, delay) {
    let lastTime = 0, timer = null;
    return function(...args) {
        const now = Date.now();
        const remaining = delay - (now - lastTime);
        if (remaining <= 0) {
            if (timer) {
                clearTimeout(timer);
                timer = null;
            }
            func.apply(this, args);
            lastTime = now;
        } else if (!timer) {
            timer = setTimeout(() => {
                func.apply(this, args);
                lastTime = Date.now();
                timer = null;
            }, remaining);
        }
    };
}

5.應(yīng)用示例

監(jiān)聽(tīng)滾動(dòng)事件時(shí),限制處理函數(shù)的頻率:

const handleScroll = throttle(() => {
    console.log('Scroll event throttled');
}, 200);
window.addEventListener('scroll', handleScroll);

6.注意事項(xiàng)

  • 間隔時(shí)間:根據(jù)實(shí)際場(chǎng)景調(diào)整 delay 參數(shù),避免卡頓或響應(yīng)不足。
  • 上下文綁定:使用 apply 確保函數(shù)內(nèi)的 this 指向正確。
  • 取消機(jī)制:可擴(kuò)展功能,支持手動(dòng)取消未執(zhí)行的定時(shí)器。

九、遞歸函數(shù)的優(yōu)缺點(diǎn)

1.優(yōu)點(diǎn)

  • 代碼簡(jiǎn)潔清晰

遞歸能將復(fù)雜問(wèn)題分解為相似的子問(wèn)題,代碼邏輯更接近數(shù)學(xué)定義或自然語(yǔ)言描述。例如階乘、斐波那契數(shù)列的實(shí)現(xiàn)只需幾行代碼。

  • 減少顯式循環(huán)結(jié)構(gòu)

對(duì)于樹(shù)形結(jié)構(gòu)(如DOM遍歷、目錄掃描)或分治算法(如快速排序、歸并排序),遞歸無(wú)需手動(dòng)維護(hù)?;蜓h(huán)變量,降低實(shí)現(xiàn)復(fù)雜度。

  • 天然的問(wèn)題分解能力

適合解決具有自相似性的問(wèn)題(如漢諾塔、回溯算法),子問(wèn)題的解能直接組合成原問(wèn)題的解。

2.缺點(diǎn)

  • 棧溢出風(fēng)險(xiǎn)

每次遞歸調(diào)用會(huì)占用棧幀空間,深度過(guò)大時(shí)(如未優(yōu)化的斐波那契數(shù)列計(jì)算)可能導(dǎo)致棧溢出錯(cuò)誤。尾遞歸優(yōu)化可緩解此問(wèn)題,但并非所有語(yǔ)言支持。

  • 性能開(kāi)銷(xiāo)較高

函數(shù)調(diào)用涉及壓棧、跳轉(zhuǎn)等操作,比循環(huán)開(kāi)銷(xiāo)更大。例如計(jì)算fib(30)可能觸發(fā)數(shù)百萬(wàn)次遞歸調(diào)用,而迭代法只需幾十次循環(huán)。

  • 調(diào)試難度增加

多層遞歸時(shí),調(diào)用棧跟蹤復(fù)雜,錯(cuò)誤可能難以定位。需依賴(lài)日志或調(diào)試工具觀察中間狀態(tài)。

  • 重復(fù)計(jì)算問(wèn)題

某些遞歸(如樸素斐波那契實(shí)現(xiàn))會(huì)重復(fù)計(jì)算相同子問(wèn)題,需配合備忘錄(Memoization)優(yōu)化。

# 未優(yōu)化的斐波那契遞歸
def fib(n):
    if n <= 1:
        return n
    return fib(n-1) + fib(n-2)  # 存在大量重復(fù)計(jì)算

3.使用建議

  • 適用場(chǎng)景:?jiǎn)栴}可明確分解為子問(wèn)題,且子問(wèn)題與原問(wèn)題同構(gòu)(如樹(shù)的遍歷)。
  • 避免場(chǎng)景:對(duì)性能敏感或遞歸深度不可控時(shí)(如處理用戶(hù)輸入的未知層級(jí)數(shù)據(jù))。
  • 優(yōu)化手段:尾遞歸改寫(xiě)(如Scheme)、備忘錄模式(緩存中間結(jié)果)、改用迭代實(shí)現(xiàn)。

十、什么是純函數(shù)

1.定義

純函數(shù)是指在相同的輸入下始終返回相同的輸出,并且不會(huì)產(chǎn)生任何副作用的函數(shù)。這意味著純函數(shù)不依賴(lài)于外部狀態(tài),也不會(huì)修改外部狀態(tài)。

2.特性

  • 確定性:對(duì)于相同的輸入,純函數(shù)總是返回相同的輸出。例如:
function add(a, b) {
  return a + b;
}

無(wú)論何時(shí)調(diào)用 add(2, 3),結(jié)果始終是 5

  • 無(wú)副作用:純函數(shù)不會(huì)修改外部變量、全局狀態(tài)或傳入的參數(shù)。例如:
let counter = 0;
function increment() {
  counter++; // 副作用:修改了外部變量
}

increment 不是純函數(shù),因?yàn)樗薷牧送獠孔兞?counter。

3.優(yōu)點(diǎn)

  • 可預(yù)測(cè)性:由于純函數(shù)的行為完全由輸入決定,結(jié)果更容易預(yù)測(cè)和測(cè)試。
  • 可緩存性:相同的輸入總是對(duì)應(yīng)相同的輸出,因此可以緩存結(jié)果以提高性能。
  • 易于并行化:純函數(shù)不依賴(lài)外部狀態(tài),可以在多線(xiàn)程環(huán)境下安全運(yùn)行。

4示例

// 純函數(shù)
function square(x) {
  return x * x;
}
// 非純函數(shù)
function getRandomNumber() {
  return Math.random(); // 輸出不確定
}

5.如何編寫(xiě)

避免修改外部狀態(tài)或傳入的參數(shù):

// 不純的函數(shù)
function updateUser(user) {
  user.age = 30; // 直接修改了參數(shù)
  return user;
}
// 純函數(shù)
function updateUserPure(user) {
  return { ...user, age: 30 }; // 返回新對(duì)象,不修改原參數(shù)
}

避免依賴(lài)外部變量:

// 不純的函數(shù)
let taxRate = 0.1;
function calculateTax(amount) {
  return amount * taxRate; // 依賴(lài)外部變量
}
// 純函數(shù)
function calculateTaxPure(amount, rate) {
  return amount * rate; // 所有依賴(lài)都通過(guò)參數(shù)傳入
}

十一、解釋函數(shù)重載在JavaScript中的實(shí)現(xiàn)方式

1.概念

函數(shù)重載允許同一函數(shù)名根據(jù)參數(shù)類(lèi)型或數(shù)量不同執(zhí)行不同操作。JavaScript本身不支持傳統(tǒng)意義上的函數(shù)重載(如Java或C++),但可以通過(guò)特定技巧模擬實(shí)現(xiàn)。

2.基于參數(shù)數(shù)量的重載

通過(guò)檢查arguments對(duì)象或剩余參數(shù)(rest parameters)判斷傳入?yún)?shù)數(shù)量,執(zhí)行不同邏輯:

function example() {
  if (arguments.length === 1) {
    console.log("處理單參數(shù)邏輯");
  } else if (arguments.length === 2) {
    console.log("處理雙參數(shù)邏輯");
  }
}
example("A");       // 輸出: 處理單參數(shù)邏輯
example("A", "B");  // 輸出: 處理雙參數(shù)邏輯

3.基于參數(shù)類(lèi)型的重載

使用typeofinstanceof檢查參數(shù)類(lèi)型,動(dòng)態(tài)調(diào)整行為:

function process(input) {
  if (typeof input === "string") {
    console.log("處理字符串邏輯");
  } else if (typeof input === "number") {
    console.log("處理數(shù)字邏輯");
  }
}
process("text");  // 輸出: 處理字符串邏輯
process(42);      // 輸出: 處理數(shù)字邏輯

4.使用對(duì)象參數(shù)模擬重載

通過(guò)傳遞配置對(duì)象統(tǒng)一參數(shù),避免參數(shù)順序問(wèn)題:

function configure(options) {
  if (options.mode === "fast") {
    console.log("啟用快速模式");
  } else if (options.mode === "safe") {
    console.log("啟用安全模式");
  }
}
configure({ mode: "fast" });  // 輸出: 啟用快速模式

5.結(jié)合默認(rèn)參數(shù)與條件判斷

利用ES6默認(rèn)參數(shù)簡(jiǎn)化邏輯分支:

function load(data, format = "json") {
  if (format === "json") {
    console.log("解析JSON數(shù)據(jù)");
  } else if (format === "xml") {
    console.log("解析XML數(shù)據(jù)");
  }
}
load({});              // 輸出: 解析JSON數(shù)據(jù)
load({}, "xml");       // 輸出: 解析XML數(shù)據(jù)

6.注意事項(xiàng)

  • JavaScript函數(shù)重載本質(zhì)是手動(dòng)模擬,需顯式編寫(xiě)參數(shù)檢查邏輯。
  • 過(guò)度使用可能導(dǎo)致代碼可讀性下降,建議優(yōu)先考慮清晰命名的獨(dú)立函數(shù)。
  • TypeScript提供更規(guī)范的重載語(yǔ)法支持,適合大型項(xiàng)目。

十二、什么是偏函數(shù)

1.概念

偏函數(shù)(Partial Function)是一種在函數(shù)式編程中常見(jiàn)的概念,指的是通過(guò)固定一個(gè)函數(shù)的部分參數(shù),生成一個(gè)新的函數(shù)。這種技術(shù)允許開(kāi)發(fā)者復(fù)用已有函數(shù),同時(shí)減少重復(fù)代碼。

2.作用

偏函數(shù)的主要作用是將一個(gè)多參數(shù)函數(shù)轉(zhuǎn)換為一個(gè)參數(shù)較少的函數(shù)。通過(guò)預(yù)先綁定某些參數(shù),可以在后續(xù)調(diào)用時(shí)簡(jiǎn)化操作。例如,一個(gè)計(jì)算乘方的函數(shù)可以通過(guò)偏函數(shù)固定底數(shù),生成一個(gè)專(zhuān)門(mén)計(jì)算平方或立方的函數(shù)。

3.實(shí)現(xiàn)方式

在Python中,可以使用functools.partial來(lái)實(shí)現(xiàn)偏函數(shù)。以下是一個(gè)示例:

from functools import partial
def power(base, exponent):
    return base ** exponent
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5))  # 輸出25
print(cube(3))    # 輸出27

4.優(yōu)點(diǎn)

  1. 代碼復(fù)用:通過(guò)固定部分參數(shù),避免重復(fù)編寫(xiě)相似的函數(shù)。
  2. 靈活性:可以在運(yùn)行時(shí)動(dòng)態(tài)生成新的函數(shù),適應(yīng)不同的需求。
  3. 可讀性:通過(guò)賦予偏函數(shù)有意義的名稱(chēng),提升代碼的可讀性。

5.應(yīng)用場(chǎng)景

  1. 回調(diào)函數(shù):在事件處理中,可以通過(guò)偏函數(shù)預(yù)先綁定部分參數(shù),簡(jiǎn)化回調(diào)函數(shù)的定義。
  2. 配置函數(shù):在需要多次調(diào)用同一函數(shù)但部分參數(shù)固定的場(chǎng)景中,使用偏函數(shù)可以減少冗余代碼。
  3. 數(shù)學(xué)運(yùn)算:如上述示例所示,通過(guò)偏函數(shù)可以快速生成特定運(yùn)算的函數(shù)。

6.注意事項(xiàng)

  1. 參數(shù)順序:偏函數(shù)綁定的參數(shù)順序需與原函數(shù)一致,否則可能導(dǎo)致錯(cuò)誤。
  2. 不可變參數(shù):偏函數(shù)生成的新函數(shù)不能修改已綁定的參數(shù)值。
  3. 性能開(kāi)銷(xiāo):盡管偏函數(shù)的性能開(kāi)銷(xiāo)通常較小,但在高性能場(chǎng)景中仍需謹(jǐn)慎使用。

到此這篇關(guān)于JavaScript函數(shù)和作用域(經(jīng)典面試題)的文章就介紹到這了,更多相關(guān)js函數(shù)和作用域內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論