簡述 JS 中對象的創建和拷貝

在 JavaScript 中,對象是一種非常重要且靈活的數據結構,用于存儲多個值(屬性)和方法(函數)

對象的創建和拷貝是日常開發中經常涉及的操作,對于業務邏輯的準確實現有著重要的作用

本文將簡要概括 JavaScript 中對象的創建和拷貝方式,都是一些非常基礎的知識,大家看個樂就好~

目錄

  • 對象的作用
  • 創建對象
    • 對象字面量
    • 使用 new Object() 方法
    • 構造函數
    • Object.create()
    • 類(ES6+)
  • 對象的拷貝
    • 深拷貝與淺拷貝的區別
    • 如何實現深拷貝
    • 展開運算符是深拷貝還是淺拷貝
  • 補充知識點:JS 中有哪些數據類型?
  • 面試問題合集

對象的作用

JavaScript中的對象是一種復合數據類型,用于存儲多個值(屬性)和方法(函數)。它主要有以下作用:

  • 組織數據:對象可以存儲和管理相關數據,使數據處理更加結構化。
  • 封裝功能:對象可以包含相關的函數,便于管理和使用。
  • 數據抽象:對象允許隱藏內部實現細節,只暴露必要的操作接口。
  • 模擬現實世界實體:對象是現實世界實體的良好抽象,有助于在程序中模擬現實世界的行為和屬性。

創建對象

在JavaScript中,創建對象是非常常見的操作,因為對象是一種非常靈活的數據結構,用于存儲和組織數據。以下是創建對象的幾種主要方式及其特點:

1. 對象字面量

這是創建對象最簡單也是最直接的方式。通過大括號 {} 來定義一個新對象,可以在其中直接定義屬性和方法。

let person = {name: "Alice",age: 25,greet: function() {console.log("Hello, " + this.name);}
};

優點:簡單直觀,易于閱讀和寫入。
缺點:不適合創建具有相同屬性和方法的多個實例。

2. 使用 new Object() 方法

這種方法使用 new Object() 構造函數來創建一個新的空對象。這是一種較為基礎的方法,與對象字面量 {} 類似,但使用了構造函數的形式。

let person = new Object();
person.name = "Eve";
person.age = 28;
person.greet = function() {console.log("Hello, " + this.name);
};

優點

  • 明確表達了創建對象的意圖。
  • 可以動態添加屬性和方法。

缺點

  • 與使用對象字面量相比,沒有明顯的優勢,而且寫法更繁瑣。
  • 每次使用 new Object() 都會創建一個全新的對象實例,如果需要創建多個結構相同的對象,這種方式不如使用構造函數或類那樣高效。
比較 new Object(){}

實際上,new Object() 和對象字面量 {} 在功能上是等價的。對象字面量的語法更簡潔、更直觀,因此在實際開發中更常被使用。例如,以下兩種創建空對象的方式是等效的:

let obj1 = new Object();
let obj2 = {};

通常,推薦使用對象字面量的方式,因為它更簡潔且易于閱讀和維護。
然而,了解 new Object() 的存在和用法也是有益的,特別是在需要通過某些特定的構造函數動態決定對象類型的高級用法中。

3. 構造函數

可以定義一個構造函數,然后用 new 關鍵字來創建對象的實例。

function Person(name, age) {this.name = name;this.age = age;this.greet = function() {console.log("Hello, " + this.name);};
}
let person1 = new Person("Bob", 30);

優點:適合創建多個具有相似屬性和方法的對象。
缺點:每個實例都會重新定義方法,可能導致內存浪費。

4. Object.create()

Object.create() 方法可以用來創建一個新對象,使用現有的對象來提供新創建的對象的__proto__

const proto = {greet: function() {console.log("Hello, " + this.name);}
};let person = Object.create(proto);
person.name = "Charlie";
person.age = 20;person.greet();

優點:可以指定原型對象,適合實現原型繼承。
缺點:不如構造函數直觀,使用稍復雜。

5. 類(ES6+)

ES6 引入了類的概念,使得創建對象更接近傳統面向對象編程。

class Person {constructor(name, age) {this.name = name;this.age = age;}greet() {console.log("Hello, " + this.name);}
}let person = new Person("Dave", 40);

優點:語法清晰,易于理解和繼承,更接近傳統的OOP語法。
缺點:較新的語法,舊版瀏覽器可能不支持。

對象的拷貝

在 JavaScript 中,理解深拷貝和淺拷貝的區別及其實現方式對于管理復雜數據結構非常重要。以下是深拷貝和淺拷貝的區別和實現方法的詳解:

深拷貝與淺拷貝的區別

  1. 淺拷貝(Shallow Copy)
    • 淺拷貝只復制對象的第一層屬性。如果屬性值是基本數據類型,拷貝的是值;如果屬性值是引用數據類型(如對象或數組),拷貝的是內存地址(引用),因此原始數據和拷貝數據會共享相同的引用對象。
    • 修改引用數據類型的屬性時,原始對象和拷貝對象都會受到影響。
  2. 深拷貝(Deep Copy)
    • 深拷貝會遞歸復制所有層級的屬性,確保原始數據和拷貝數據在內存中完全獨立。修改拷貝對象不會影響原始對象。
    • 實現深拷貝通常需要遞歸調用或使用特定的庫函數。

如何實現深拷貝

  1. 使用 JSON 方法
    • 最簡單的深拷貝實現可以通過 JSON 的序列化和反序列化完成。但這種方法不能復制函數、undefinedSymbol 等特殊類型的數據,也無法處理循環引用的情況。
    const obj = {a: 1,b: {c: 2}
    };
    const deepCopy = JSON.parse(JSON.stringify(obj));
    deepCopy.b.c = 3;
    console.log(obj.b.c); // 輸出 2
    
  2. 使用庫(如 Lodash 的 cloneDeep 方法)
    • 一些 JavaScript 庫如 Lodash 提供了深拷貝的實現。這些實現通常更為完整,能處理各種數據類型和復雜的數據結構。
    import _ from 'lodash';
    const obj = {a: 1,b: {c: 2}
    };
    const deepCopy = _.cloneDeep(obj);
    deepCopy.b.c = 3;
    console.log(obj.b.c); // 輸出 2
    
  3. 手動實現遞歸深拷貝
    • 你可以手動編寫一個遞歸函數來實現深拷貝。這種方法需要處理各種數據類型和循環引用的問題。
    function deepClone(obj, hash = new WeakMap()) {if (obj === null) return null; if (typeof obj !== 'object') return obj;if (obj instanceof Date) return new Date(obj);if (obj instanceof RegExp) return new RegExp(obj);if (hash.has(obj)) return hash.get(obj);const cloneObj = new obj.constructor();hash.set(obj, cloneObj);for (const key in obj) {if (obj.hasOwnProperty(key)) {cloneObj[key] = deepClone(obj[key], hash);}}return cloneObj;
    }
    

開發中如何避免淺拷貝

  • 在處理復雜的數據結構時,尤其是包含嵌套對象或數組時,避免使用如 Object.assign() 或展開運算符(...)這樣的淺拷貝方法。
  • 使用深拷貝方法(如上述的 JSON 方法或 Lodash 的 cloneDeep)來確保數據的完整獨立性。
  • 在不需要完整拷貝對象的情況下,明確你的需求,選擇合適的拷貝策略。

展開運算符是深拷貝還是淺拷貝

展開運算符(spread operator)在 JavaScript 中用于“展開”數組或對象的元素。
當用于對象或數組時,展開運算符僅復制第一層的元素到新的數組或對象中。
這意味著如果原始數據結構中包含嵌套的對象或數組,這些嵌套的結構不會被真正地復制,而是復制它們的引用。
因此,展開運算符實際上進行的是淺拷貝。

示例:對象的淺拷貝
const original = {a: 1,b: {c: 2}
};
const copied = { ...original };
copied.a = 3; // 修改基本類型值
copied.b.c = 3; // 修改引用類型值
console.log(original); // 輸出:{ a: 1, b: { c: 3 } }
console.log(copied);  // 輸出:{ a: 3, b: { c: 3 } }

在這個例子中,修改 copied.b.c 同時也改變了 original.b.c,因為 b 屬性的值(一個對象)通過引用被復制到了 copied 對象中。

示例:數組的淺拷貝
const originalArray = [1, { b: 2 }, 3];
const copiedArray = [...originalArray];
copiedArray[1].b = 3; // 修改數組中對象的屬性
console.log(originalArray); // 輸出:[1, { b: 3 }, 3]
console.log(copiedArray);  // 輸出:[1, { b: 3 }, 3]

這個例子同樣展示了修改 copiedArray 中的對象屬性 b 時,originalArray 中相應的屬性也被改變了。這是因為數組中的對象是通過引用被復制的。

補充知識點:JS 中有哪些數據類型?

在 JavaScript 中,數據類型分為兩大類:基本數據類型(Primitive types)和引用數據類型(Reference types)。
理解這兩種類型的區別對于掌握 JavaScript 的數據操作和性能優化非常重要。

基本數據類型(Primitive types)

基本數據類型直接存儲在棧(Stack)中,它們的值是不可變的。
當你對基本數據類型的變量進行操作時,實際上是在操作它的值的副本,而不是原始值本身。JavaScript 中的基本數據類型包括:

  1. Number: 用于表示整數或浮點數,也包括特殊的數值如 Infinity, -Infinity, 和 NaN
  2. BigInt: 用于表示非常大的整數,超出了 Number 類型能夠表示的范圍。
  3. String: 由字符組成的序列,用于表示文本數據,使用單引號、雙引號或反引號表示。
  4. Boolean: 表示邏輯實體,只有兩個值,truefalse,用于邏輯判斷。
  5. Undefined: 一個變量被聲明了,但沒有賦值時,它的值就是 undefined
  6. Null: 表示沒有值或空值。通常用來表示變量將不會存儲任何值。
  7. Symbol: ES6 引入的新的基本數據類型,每個 Symbol 的值都是唯一的,常用于創建對象的私有成員。

引用數據類型(Reference types)

引用數據類型的值是對象,存儲在堆(Heap)中,變量實際上存儲的是一個指向堆內存中實際對象的指針。這意味著當你操作一個對象時,你是在操作對象的引用而不是實際的對象。引用數據類型包括:

  1. Object: 基本的對象類型,幾乎所有的 JavaScript 對象都是 Object 類型的實例。
    • Date: 用于處理日期和時間。
    • RegExp: 用于定義正則表達式。
    • ArrayFunction也都是對象。
    • 其他如 Map, Set, WeakMap, WeakSet 等也屬于對象。
  2. Array: 用于存儲有序集合的對象。
  3. Function: 函數實際上是一種特殊類型的對象,它具有可被執行的功能。

特殊提及

BigInt: ES2020 引入的一種新的數字類型,可以表示非常大的整數。
傳統的 Number 類型只能安全地表示 -2^53 + 12^53 - 1 之間的整數,而 BigInt 可以表示任意大的整數。

類型檢測

可以使用 typeof 操作符來檢查一個變量的類型,除了 null 返回的是 "object"
對于更復雜的類型判斷,通常使用 instanceof 操作符或者 Object.prototype.toString.call() 方法。

總結

  • 基本數據類型:Number, String, Boolean, Undefined, Null, Symbol, BigInt
  • 引用數據類型:Object (包括 Array, Function, Date, RegExp 等)
    JavaScript 的靈活性在很大程度上來自于它的動態類型系統和對各種數據類型的支持。
    理解這些數據類型及其使用場景對于編寫有效和高效的 JavaScript 代碼至關重要。
    了解這些類型及其分類有助于更好地理解 JavaScript 的內存管理和性能優化,以及如何在代碼中有效地處理數據。

面試問題合集

恭喜你耐心看完本文了,對照下方的問題列表,自我提問一下吧~

js中對象的作用是什么?
js中如何創建對象?有哪些方式?
js中創建對象不同方式的區別是什么?優缺點有哪些?
js中對象的深拷貝和淺拷貝有什么區別?
js中如何實現對象的深拷貝?
js中開發中如何避免發生對象的淺拷貝?
js中的展開運算符是深拷貝還是淺拷貝?
js中有哪些數據類型?

我是 fx67ll.com,如果您發現本文有什么錯誤,歡迎在評論區討論指正,感謝您的閱讀!
如果您喜歡這篇文章,歡迎訪問我的 本文github倉庫地址,為我點一顆Star,Thanks~ 😃
轉發請注明參考文章地址,非常感謝!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/42813.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/42813.shtml
英文地址,請注明出處:http://en.pswp.cn/web/42813.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux查看目錄下的文件夾命令,find 查找某個目錄,但是不包括這個目錄本身?

linux查看目錄下的文件夾命令,find 查找某個目錄,但是不包括這個目錄本身? Linux中查看目錄下的文件夾的命令是使用ls命令。ls命令用于列出指定目錄中的文件和文件夾。通過不同的選項可以實現顯示詳細信息、按照不同的排序方式以及使用不同的…

Profibus轉ModbusTCP網關模塊實現Profibus_DP向ModbusTCP轉換

Profibus和ModbusTCP是工業控制自動化常用的二種通信協議。Profibus是一種串口通信協議,它提供了迅速靠譜的數據傳輸和各種拓撲結構,如總線和星型構造。Profibus可以和感應器、執行器、PLC等各類設備進行通信。 ModbusTCP是一種基于TCP/IP協議的通信協議…

一次零基礎 自“信息收集“到“權限維持“的滲透測試全程詳細記錄

一、滲透總流程 1.確定目標: 在本靶場中,確定目標就是使用各種掃描工具進行ip掃描,確定目標ip。 2.信息收集: 比如平常挖洞使用fofa,天眼查,ip域名等進行查,在我們這個靶場中比如使用Wappalyz…

基于網絡編碼的 tcp 變種-tcp/nc

tcp/nc 是指 “tcp with network coding”,是一種結合了網絡編碼技術的 tcp 變種,網上資源很少,我也不準備多介紹,只介紹它的核心。 傳統 tcp 在演進過程中一直搞不定效率問題,網絡帶寬在增長,cpu 卻沒有變…

C++類和對象(上篇)

文章目錄 前言一、面向過程和面向對象初步認識 二、類的引入 三、類的定義 六、類的實例化 七、類的對象大小的計算 八、類成員函數的this指針 總結 前言 類和對象是面向對象編程的兩個核心概念。 類是一種抽象的數據類型,是描述對象共同特征和行為的模板。一個類…

yolov5:Conv類參數量計算

Conv是yolov5自定義的類,里邊包含了卷積層、BN層和激活函數 class Conv(nn.Module):# Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)default_act nn.SiLU() # default activationdef __init__(self, c…

點云下采樣有損壓縮

轉自本人博客&#xff1a;點云下采樣有損壓縮 點云下采樣是通過一定規則對原點云數據進行再采樣&#xff0c;減少點云個數&#xff0c;降低點云稀疏程度&#xff0c;減小點云數據大小。 1. 體素下采樣&#xff08;Voxel Down Sample&#xff09; std::shared_ptr<PointClo…

華為機考真題 -- 信道分配

題目描述&#xff1a; 算法工程師小明面對著這樣一個問題&#xff0c;需要將通信用的信道分配給盡量多的用戶&#xff0c; 信道的條件及分配規則如下&#xff1a; 1) 所有信道都有屬性&#xff1a;”階”。階為 r 的信道容量為 2^r 比特&#xff1b; 2) 所有用戶需要傳輸的數…

區間貪心

目錄 1.貪心算法的思想 2.區間貪心算法常用的一些題目類型 1.選擇最多不相交區間問題 P2970 [USACO09DEC] Selfish Grazing S 1.思路分析 2.上代碼 2.區間選點問題 P1250 種樹 1.題目 2.方法一 1.代碼解釋 3.方法二 3.區間合并問題 P2434 [SDOI2005] 區間 1. 思路…

中科海訊 C++初級研發工程師筆試題目

C語言中的const關鍵字有什么作用&#xff1f;為什么要使用const關鍵字&#xff1f; 1 const修飾的變量將會被放到常量區&#xff0c;避免被意外的改動。 const修飾的常量比#define修飾的有更多的優勢&#xff0c;比如可以調試&#xff0c;類型檢查等 2 const修飾的參數可做輸入…

Java集合面試題

Java集合框架 1、List、Set、Map的區別2、ArrayList、LinkedList、Vector區別3、為什么數組索引從0開始&#xff0c;而不是從1開始&#xff1f;4、ArrayList底層的實現原理5、紅黑樹、散列表6、HashMap的底層原理7、HashMap的put方法具體流程8、HashMap的擴容機制9、HashMap是怎…

南方科技大學馬永勝教授給年輕人使用AI工具上的建議

摘要 - 1. AI的未來&#xff0c;是機器人和機器人之間的合作&#xff1b; 2. 行業的發展方向是需求決定的&#xff0c;不要做同質化的發展&#xff0c;要做專/精/特/新&#xff1b; 3. 新質生產力 &#xff08; 科學技術革命性突破 生產要素創新型配置 產業深度轉型升級&…

java通過poi-tl導出word實戰詳細步驟

文章目錄 與其他模版引擎對比1.引入maven依賴包2.新建Word文檔exportWprd.docx模版3.編寫導出word接口代碼4.導出成果 poi-tl是一個基于Apache POI的Word模板引擎&#xff0c;也是一個免費開源的Java類庫&#xff0c;你可以非常方便的加入到你的項目中&#xff0c;并且擁有著讓…

貪心算法-以高校教材管理系統為例

1.貪心算法介紹 1.算法思路 貪心算法的基本思路是從問題的某一個初始解出發一步一步地進行&#xff0c;根據某個優化測度&#xff0c;每一 步都要確保能獲得局部最優解。每一步只考慮一 個數據&#xff0c;其選取應該滿足局部優化的條件。若下 一個數據和部分最優解連在一起…

Pix4Dmapper:無人機測繪的革命性工具

在現代測繪和地理信息系統&#xff08;GIS&#xff09;領域&#xff0c;Pix4Dmapper無疑是一款革命性的工具。作為一名長期使用這款軟件的用戶&#xff0c;我深深感受到它在工作中的重要性和便利性。Pix4Dmapper不僅僅是一款軟件&#xff0c;更是測繪工作者的得力助手&#xff…

285個地級市出口產品質量及技術復雜度(2011-2021年)

出口產品質量與技術復雜度&#xff1a;衡量國家競爭力的關鍵指標 出口產品質量是衡量國內企業生產的產品在國際市場上競爭力的重要標準。它不僅要求產品符合國際標準和目標市場的法律法規&#xff0c;而且需要保證產品質量的穩定性和可靠性。而出口技術復雜度則進一步體現了一…

新一代信息技術及應用

關于云計算的描述不正確的是&#xff08; &#xff09;。 A 云計算可以通過網絡連接&#xff0c;用戶通過網絡接入“云”中并獲得有關的服務&#xff0c;“云”內節點之間也通過內部的網絡相連 B 云計算可以快速、按需、彈性服務&#xff0c;用戶可以按照實際需求迅速獲取或釋放…

[Python學習篇] Python面向對象——類

面向對象是什么&#xff1f; 面向對象&#xff08;Object-Oriented Programming&#xff0c;簡稱OOP&#xff09;是一種編程范式&#xff0c;它使用“對象”來設計應用程序和計算機程序。OOP的核心概念包括類&#xff08;Class&#xff09;、對象&#xff08;Object&#xff09…

批量下載手機中APP程序中文件

需求 利用 adb pull 下載手機中app的某目錄 adb pull 命令本身不支持直接下載整個目錄&#xff08;文件夾&#xff09;及其所有子目錄和文件作為一個單一的操作。但是&#xff0c;可以通過一些方法來間接實現這一目的。 方法 1. 首先將要下載的目錄進行 tar 打包 # 在 And…

Python面試題:Python 中的 `property` 函數有什么用?

在 Python 中&#xff0c;property 函數用于創建和管理類中的屬性。它允許你將方法轉換為屬性&#xff0c;這樣你可以像訪問變量一樣訪問這些方法。這對于控制屬性的訪問和修改非常有用&#xff0c;因為它允許你在屬性訪問時執行額外的邏輯&#xff08;如驗證或計算&#xff09…