成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

超好運的大廠實習(帶轉正)面試,直接拿下!猛猛的!

開發
const 聲明的是一個不可重新賦值的變量,但它的值(如果是對象或數組)可以是可變的。

Hello,大家好,我是 Sunday。

運氣也是實力的一部分,此話誠不欺我!

最近有位同學,校招面試攜程,一面、二面,都是純八股文的面試。這可是 帶轉正的 HC 呀! 直接輕松拿下。

實習一天 220,額外加 1000/月 的房補。在大廠中算是中等水平。

那么下面咱們就來看看這次面試,都聊了什么問題吧!

一、improt和require的區別

import 和 require 是 JavaScript 中用來導入模塊的兩種不同的語法,主要用于 ES6 和 CommonJS 模塊系統。以下是它們的主要區別:

1. 模塊系統

  • require: 屬于 CommonJS 模塊系統,主要用于 Node.js 中。它是同步加載模塊的,適合在服務器端使用。
  • import: 屬于 ES6 模塊系統(也稱為 ECMAScript 模塊)。它支持異步加載,適合在瀏覽器端和現代 JavaScript 環境中使用。

2. 語法

  • require:
const module = require('module-name');
  • import:
import module from 'module-name'; // 導入默認導出
import { namedExport } from 'module-name'; // 導入命名導出
import * as allExports from 'module-name'; // 導入所有導出

3. 加載時機

  • require: 在代碼運行時被調用,模塊在被調用時才會被加載,因此是同步的。
  • import: 在編譯階段被處理,模塊會在模塊代碼執行前被加載,因此是異步的。

4. Hoisting(提升)

  • require: 不會提升,必須在代碼中顯式調用。
  • import: 會提升,可以在文件的任何位置使用,但在模塊的頂部進行導入是最佳實踐。

5. 導出方式

CommonJS 導出:

// 導出模塊
module.exports = {
    functionA: function() {},
    functionB: function() {},
};

ES6 導出:

// 導出默認
export default functionA;

// 導出命名
export function functionB() {}

6. 循環依賴處理

  • require: 處理循環依賴時,返回的是已經加載的模塊部分。
  • import: 在循環依賴的情況下,會引發錯誤,因為它在模塊解析階段就會出錯。

7. 總結

  • require: 適合 Node.js 和后端開發,采用同步加載的方式。
  • import: 更加現代,適合前端開發,支持異步加載和靜態分析。

在現代前端開發中,建議使用 ES6 的 import 語法,因為它提供了更好的模塊化和可維護性。

二、require 有辦法實現異步嗎?

在 Node.js 中,require 本身是同步的,但可以通過一些其他方式實現異步模塊加載。以下是幾種方法:

1. 使用 import()

從 ES6 開始,可以使用動態 import() 函數來實現異步加載模塊。雖然它與 require 不同,但在現代 JavaScript 環境中是推薦的方式。

async function loadModule() {
    const module = await import('./module.js');
    module.someFunction();
}

2. 使用 require 結合回調

可以在回調中使用 require,盡管這并不是真正的異步加載,但可以通過事件循環達到異步效果。

function loadModule(callback) {
    setTimeout(() => {
        const module = require('./module.js');
        callback(module);
    }, 0);
}

loadModule((module) => {
    module.someFunction();
});

3. 使用 require 結合 Promise

通過 Promise 的方式包裹 require,達到異步的效果:

function loadModule() {
    return new Promise((resolve) => {
        setTimeout(() => {
            const module = require('./module.js');
            resolve(module);
        }, 0);
    });
}

loadModule().then((module) => {
    module.someFunction();
});

4. 使用 async_hooks

在更復雜的場景中,可以使用 Node.js 的 async_hooks 模塊來處理異步上下文,但這通常不適用于簡單的模塊加載需求。

5. 總結

雖然 require 本身是同步的,不能直接實現異步模塊加載,但可以使用動態 import() 或通過回調和 Promise 來模擬異步行為。在現代開發中,推薦使用 ES6 的動態 import(),因為它更具可讀性和一致性。

三、export 和 export default的區別

export 和 export default 是 ES6 中用于導出模塊的兩種方式,它們的主要區別如下:

1. 導出方式

(1) export

// module.js
export const a = 1;
export const b = 2;
export function add(x, y) {
    return x + y;
}
// main.js
import { a, add } from './module.js';
console.log(a); // 1
console.log(add(1, 2)); // 3

允許在一個模塊中導出多個變量、函數或類。

導出時不需要指定名稱,可以在導入時使用 {} 指定要導入的變量名稱。

(2) export default

// module.js
const multiply = (x, y) => x * y;
export default multiply;
// main.js
import multiply from './module.js';
console.log(multiply(2, 3)); // 6

每個模塊只能有一個默認導出。

在導入時可以使用任何名稱,不需要使用 {}。

2. 導入方式

使用export的導入:

import { a, b } from './module.js';

導入時需要使用相同的名稱,且需要使用 {} 包裹。

使用export default的導入:

import myFunction from './module.js';

導入時可以自定義名稱,且不需要 {}。

3. 使用場景

  • export: 當你需要導出多個功能或變量時,適合使用 export。
  • export default: 當一個模塊有一個主要功能或對象時,適合使用 export default。

4. 組合使用

可以同時使用兩者:

// module.js
export const a = 1;
export const b = 2;
const multiply = (x, y) => x * y;
export default multiply;
// main.js
import multiply, { a } from './module.js';
console.log(a); // 1
console.log(multiply(2, 3)); // 6

5. 總結

export 允許多個命名導出,而 export default 只允許一個默認導出。

導入時,命名導出需要使用 {},而默認導入可以使用任意名稱。

四、閉包

能夠調用其他函數中變量的函數,就是 閉包函數。

function outerFunction() {
    let outerVariable = 'I am outside!';
    // innerFunction 函數使用了 outerFunction 里面的變量,所以它就是【閉包函數】
    function innerFunction() {
        console.log(outerVariable);
    }

    return innerFunction;
}

const closureFunction = outerFunction(); // outerFunction 被執行
closureFunction(); // 輸出: I am outside!

五、在什么情況下閉包會出現內存泄漏的問題

閉包在某些情況下會導致內存泄漏,主要是由于閉包持有外部變量的引用,進而阻止了這些變量的垃圾回收。以下是幾種可能導致內存泄漏的情況:

1. 循環引用

當閉包持有外部對象的引用,而該對象又持有對閉包的引用時,就會產生循環引用。這種情況會導致垃圾回收器無法正確回收內存。

function createClosure() {
    let obj = {};
    obj.closure = function() {
        console.log(obj);
    };
    return obj.closure;
}

const closure = createClosure(); // obj 和 closure 形成循環引用

在上面的例子中,obj 對象持有對閉包的引用,而閉包又引用了 obj,這導致內存無法被回收。

2. 不當使用事件監聽器

如果使用閉包作為事件監聽器并沒有在適當的時候移除它們,可能會導致內存泄漏。特別是在動態創建和銷毀 DOM 元素時。

function createElement() {
    const button = document.createElement('button');
    button.innerText = 'Click me';
    
    button.addEventListener('click', function() {
        // 使用了外部變量
        console.log('Button clicked');
    });
    
    document.body.appendChild(button);
}

// 每次調用 createElement 都會添加一個新的按鈕,但事件監聽器不會被移除
createElement();

在這個例子中,每次調用 createElement 函數都會創建一個新的按鈕并添加事件監聽器,但如果不手動移除這些監聽器,它們將一直保留在內存中。

3. 大型數據結構

當閉包持有大型數據結構(如大數組或對象)的引用時,如果這些數據結構沒有在不需要時被清理,也可能導致內存泄漏。

let largeArray = new Array(1000000).fill('data');

function createLargeDataClosure() {
    return function() {
        console.log(largeArray.length); // 持有對 largeArray 的引用
    };
}

const closure = createLargeDataClosure();

在這個例子中,closure 持有對 largeArray 的引用,如果沒有在適當的時候釋放這個引用,將會導致內存占用持續增加。

4. 使用全局作用域

如果閉包中的變量是全局變量,那么閉包會一直持有對這些全局變量的引用,直到整個程序結束。這在長時間運行的應用中,可能導致內存的不斷增長。

let globalVar = 'Hello';

function createClosure() {
    return function() {
        console.log(globalVar);
    };
}

const closure = createClosure();

在這個例子中,閉包始終引用了 globalVar,從而保持了對它的引用。

5. 預防內存泄漏的措施

  • 合理使用閉包:盡量避免不必要的閉包,尤其是在循環和事件處理器中。
  • 及時清理引用:在不再需要的時候,主動清理閉包中的引用,例如通過將事件監聽器設置為 null。
  • 使用 WeakMap 和 WeakSet:對于需要被垃圾回收的對象引用,可以使用 WeakMap 和 WeakSet,它們不會阻止垃圾回收。
  • 手動移除事件監聽器:在元素被移除時,記得手動移除事件監聽器。

通過以上方式,可以有效減少使用閉包時可能出現的內存泄漏問題。

六、說一下 JS 中原型鏈的概念

原型鏈是 JavaScript 中實現繼承的一種機制,每個對象都有一個內部屬性指向其原型對象。原型鏈是通過對象的 __proto__ 屬性或 Object.getPrototypeOf() 方法連接起來的。下面是原型鏈的基本概念以及圖示說明。

1. 原型鏈的概念

  • 原型:每個 JavaScript 對象都有一個原型,原型也是一個對象,可以有自己的原型,這樣就形成了一個鏈式結構,稱為原型鏈。
  • 構造函數:通過構造函數創建的對象會有一個 prototype 屬性,指向構造函數的原型對象。

查找順序:

  • 當訪問一個對象的屬性時,JavaScript 引擎首先在該對象自身查找。如果找不到,它會查找該對象的原型(即 __proto__ 屬性指向的對象)。
  • 如果在原型中也沒有找到,它會繼續向上查找,直到找到屬性或到達原型鏈的末端(通常是 Object.prototype),如果仍未找到,則返回 undefined。

2. 示例代碼

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

Animal.prototype.speak = function() {
  console.log(this.name + ' makes a noise.');
};

function Dog(name) {
  Animal.call(this, name); // Call the parent constructor
}

// 設置 Dog.prototype 為 Animal 的實例
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 糾正 constructor

Dog.prototype.speak = function() {
  console.log(this.name + ' barks.');
};

const dog = new Dog('Rex');
dog.speak(); // 輸出: Rex barks.

console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true

3. 解析示例

Animal 是一個構造函數,創建的實例具有 name 屬性和 speak 方法。

Dog 是另一個構造函數,它通過 Object.create(Animal.prototype) 使得 Dog.prototype 成為 Animal.prototype 的實例,從而繼承了 Animal 的方法。

dog 是 Dog 的一個實例,它可以訪問 speak 方法,雖然該方法在 Dog 的原型上被覆蓋,但它也可以訪問 Animal 的 speak 方法(如果需要的話)。

4. 小結

原型鏈是 JavaScript 繼承的基礎,允許對象共享屬性和方法。

理解原型鏈對于掌握 JavaScript 的面向對象編程、構造函數、以及如何實現繼承非常重要。

七、null有原型鏈嗎?

null 在 JavaScript 中被認為是一個特殊的原始值。它表示“無”或“空值”。在原型鏈的上下文中,null 是原型鏈的終點。

八、Array的原型是什么

在 JavaScript 中,Array 是一種內置的對象,用于處理數組。Array 的原型是 Array.prototype。這使得所有數組實例都能夠訪問 Array.prototype 上定義的方法和屬性。

1. 原型鏈結構

(1) Array.prototype:

  • Array.prototype 是所有數組對象的原型,定義了數組的方法和屬性,如 push(), pop(), map(), filter() 等。
  • 你可以在 Array.prototype 上添加自定義的方法,這樣所有數組實例都可以使用。

(2) Object.prototype:

  • 所有對象(包括數組)的原型最終都會鏈接到 Object.prototype。這意味著數組實例也繼承了 Object 的方法和屬性,如 toString(), hasOwnProperty() 等。

(3) null:

  • Object.prototype 的原型是 null,這是原型鏈的終點。

2. 示例

下面是一個示例,展示了如何通過 Array.prototype 訪問數組方法:

// 定義一個數組
const arr = [1, 2, 3];

// 訪問 Array.prototype 上的方法
console.log(arr.map(x => x * 2)); // 輸出: [2, 4, 6]

// 檢查原型
console.log(Object.getPrototypeOf(arr) === Array.prototype); // 輸出: true
console.log(Object.getPrototypeOf(Array.prototype) === Object.prototype); // 輸出: true

3. 總結

Array 的原型是 Array.prototype。

所有數組實例都可以訪問 Array.prototype 上定義的方法和屬性。

Array.prototype 又可以通過其原型鏈訪問到 Object.prototype,最終終止于 null。

九、Object的原型是什么

在 JavaScript 中,Object 是所有對象的基類。Object 的原型是 Object.prototype。這是一個包含許多通用方法和屬性的對象,所有普通對象都可以繼承這些方法和屬性。

1. 原型鏈結構

(1) Object.prototype:

  • Object.prototype 是所有對象的原型,它定義了一些通用的方法和屬性,例如 toString(), hasOwnProperty(), isPrototypeOf(), 和 valueOf() 等。
  • 所有普通對象(即通過對象字面量、構造函數或 Object.create() 創建的對象)都能夠訪問 Object.prototype 上的方法和屬性。

(2) null:

Object.prototype 的原型是 null,這是原型鏈的終點。

2. 示例

下面是一個示例,展示了如何通過 Object.prototype 訪問對象方法:

// 創建一個普通對象
const obj = {
  name: 'Alice',
  age: 30
};

// 訪問 Object.prototype 上的方法
console.log(obj.toString()); // 輸出: [object Object]
console.log(obj.hasOwnProperty('name')); // 輸出: true

// 檢查原型
console.log(Object.getPrototypeOf(obj) === Object.prototype); // 輸出: true
console.log(Object.getPrototypeOf(Object.prototype)); // 輸出: null

3. 總結

Object 的原型是 Object.prototype。

所有普通對象都可以訪問 Object.prototype 上定義的方法和屬性。

Object.prototype 的原型是 null,這是原型鏈的終點。

十、let const var的區別

let、const 和 var 是 JavaScript 中用于聲明變量的關鍵字。它們之間有一些重要的區別:

1. 聲明的作用域

(1) var:

聲明的變量具有 函數作用域。如果在函數內部使用 var 聲明變量,該變量只在該函數內可用。如果在函數外部使用 var 聲明,變量會變成全局變量。

例子:

function example() {
  var a = 10;
}
console.log(a); // ReferenceError: a is not defined

(2) let和const:

聲明的變量具有 塊級作用域。也就是說,它們只在其聲明的代碼塊內有效(例如,if 語句、for 循環等)。

例子:

{
  let b = 20;
  const c = 30;
}
console.log(b); // ReferenceError: b is not defined
console.log(c); // ReferenceError: c is not defined

2. 變量提升

(1) var:

變量會被提升到函數的頂部,初始化為 undefined。在變量聲明之前使用該變量不會報錯,但值為 undefined。

例子:

console.log(d); // undefined
var d = 5;
console.log(d); // 5

(2) let和const:

變量也會被提升,但在聲明之前是 “暫時性死區”(Temporal Dead Zone, TDZ),使用它們會導致 ReferenceError。

例子:

console.log(e); // ReferenceError: Cannot access 'e' before initialization
let e = 15;

3. 重新賦值

(1) var和let:

這兩個關鍵字聲明的變量都可以被重新賦值。

例子:

var f = 1;
f = 2; // 可以重新賦值
console.log(f); // 2

let g = 3;
g = 4; // 可以重新賦值
console.log(g); // 4

(2) const:

聲明的變量不能被重新賦值,必須在聲明時初始化。

例子:

const h = 5;
h = 6; // TypeError: Assignment to constant variable.

4. 常量和可變性

const:

用于聲明常量,但這只意味著變量的引用不可以被改變。如果 const 聲明的是一個對象或數組,可以修改其屬性或元素。

例子:

const obj = { name: 'Alice' };
obj.name = 'Bob'; // 允許,修改對象的屬性
console.log(obj.name); // Bob

5. 總結

  • var: 函數作用域、提升、可以重復聲明和賦值。
  • let: 塊級作用域、提升、可以賦值,但不能重復聲明。
  • const: 塊級作用域、提升、不能重新賦值,聲明時必須初始化。

十一、const的原理是什么?為什么不能改變

const 是 JavaScript 中用于聲明常量的關鍵字,其原理和行為主要與塊級作用域和引用類型有關。以下是對 const 的詳細解釋:

1. 塊級作用域

const 聲明的變量具有塊級作用域。這意味著它們只在定義它們的代碼塊內有效。例如,在一個 if 語句或循環內聲明的 const 變量不能在其外部訪問。

{
  const x = 10;
}
console.log(x); // ReferenceError: x is not defined

2. 不可重新賦值

const 聲明的變量不能被重新賦值。這并不是說變量本身是不可變的,而是說變量的引用(地址)是不可變的。也就是說,您不能將一個 const 變量重新指向一個新的值。

const y = 20;
y = 30; // TypeError: Assignment to constant variable.

3. 引用類型的可變性

如果 const 聲明的是一個對象或數組,您可以修改其屬性或元素,但不能改變其引用。這意味著您可以對對象的內容進行修改,但不能將該對象指向另一個對象。

const obj = { name: 'Alice' };
obj.name = 'Bob'; // 允許,修改對象的屬性
console.log(obj.name); // Bob

obj = { name: 'Charlie' }; // TypeError: Assignment to constant variable.

4. 原理解析

const 的原理在于 ECMAScript 的變量綁定機制。聲明一個 const 變量時,它會創建一個綁定到該值的不可更改的引用。以下是這一機制的詳細解讀:

  • 綁定:當您使用 const 聲明一個變量時,實際上是將該變量與一個值綁定在一起。這個綁定是固定的,您不能改變它。
  • 作用域:const 聲明的變量僅在聲明時的塊內有效,并在退出該塊后被銷毀。
  • 不可重新賦值:一旦綁定建立,就不能再將該變量指向另一個值(即不可重新賦值)。

5. 總結

const 聲明的是一個不可重新賦值的變量,但它的值(如果是對象或數組)可以是可變的。

這種設計使得 const 適用于需要保護不被重新分配的變量,同時仍允許對其內部狀態進行修改的場景。

責任編輯:趙寧寧 來源: 程序員Sunday
相關推薦

2013-04-16 10:36:41

Gartner云安全

2015-07-03 15:09:15

2022-06-14 10:41:23

CSS前端

2013-09-02 14:56:02

開發者工具前段工具后端工具

2015-05-08 08:22:27

2011-11-17 14:27:51

并購2011

2024-09-20 09:30:44

2015-04-07 15:58:51

2020-03-04 14:10:14

戴爾

2013-09-02 10:22:28

開發者工具

2020-09-08 07:01:01

調度算法

2012-08-06 12:56:51

imo即時通訊

2012-07-02 10:09:09

imo即時通訊

2019-11-29 08:00:00

技術研發技能

2013-05-02 09:15:15

2013-02-26 08:57:17

AWS亞馬遜Rackspace

2011-09-22 13:34:03

3G

2010-02-25 15:39:23

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品国产一区二区国模嫣然 | 在线成人免费观看 | 亚洲精品大片 | 国产免费一区二区三区最新6 | h片在线观看免费 | 国产精品久久久久久久岛一牛影视 | www.久久久久久久久久久 | 国产美女一区二区 | 国产精品视频免费看 | 日韩成人免费视频 | 中文久久 | 黄a在线观看 | 蜜臀网 | 国产黄色麻豆视频 | 欧美中文字幕一区二区三区 | 国产精品久久久久久久久免费丝袜 | 欧美色人 | 国产真实精品久久二三区 | xxxxx黄色片 欧美一区免费 | 久久国际精品 | 亚洲天堂二区 | 日韩欧美中文在线 | 国产精品明星裸体写真集 | 久久久久亚洲av毛片大全 | 国产十日韩十欧美 | 久久久久久久久久久久久9999 | 亚洲毛片 | 国产成人精品久久二区二区91 | 精品视频久久久 | 国产真实精品久久二三区 | 麻豆国产一区二区三区四区 | 国产一区视频在线 | 欧美极品在线观看 | 在线中文字幕亚洲 | 免费骚视频 | 欧美va大片 | 怡红院成人在线视频 | av黄色在线 | 精品久久久久久亚洲综合网 | 91久久精品一区二区二区 | 在线视频91 |