連續賦值和記憶體指針的問題解析(a.x=a={n:2})

来源:http://www.cnblogs.com/peakol/archive/2017/06/24/7074289.html
-Advertisement-
Play Games

前幾天偶然看到了一個這樣的題: 這個題代碼不多,不過考察的知識點卻非常不錯。我們知道記憶體空間分為棧記憶體和堆記憶體。棧記憶體用來存放供js代碼來執行的環境,所以為了保證性能減少記憶體占用,我們一般把占用空間較小的類似於基本數據類型放在棧記憶體中,像引用數據類型這種占據空間比較大的東西,我們需要將它放在一個貯藏 ...


  前幾天偶然看到了一個這樣的題:

1 <script>
2     var a={n:1};
3     var b=a;
4     a.x=a={n:2};//關鍵代碼
5 console.log(a.x);//undefined
6    console.log(b.x);//[object Object]
7 </script>

     這個題代碼不多,不過考察的知識點卻非常不錯。我們知道記憶體空間分為棧記憶體和堆記憶體。棧記憶體用來存放供js代碼來執行的環境,所以為了保證性能減少記憶體占用,我們一般把占用空間較小的類似於基本數據類型放在棧記憶體中,像引用數據類型這種占據空間比較大的東西,我們需要將它放在一個貯藏室中—堆記憶體中,堆記憶體相較於棧記憶體對js執行時對性能影響很小,雖然引用類型存放在堆記憶體里了,但是當我們代碼執行時我們也需要用到這部分,所以我們需要將類似於標簽,名字(類似於元素的ID)放置於棧記憶體中,和堆記憶體中的東西一一對應,當執行到他時直接去堆記憶體中找,這種模式就好比古代的銀票和同等價值的黃金和白銀,一個很有錢的商人不能每次出門都推著一車銀子吧,那可是金屬,那這樣有錢人活的就太累了,所以一個等面值的銀票揣在手中,一切問題就搞定了。 所以“不同變數的同一引用數據類型賦值就是指向的是同一個堆記憶體空間,不會去創造新的記憶體空間,不然太浪費空間了,你要知道這可是記憶體,記憶體呀!!”

   1. 像此題中一樣 var a={n:1};    var b=a;  這是並沒有給變數b在堆記憶體中在創建一個對象{n:1},而是他倆共同指向記憶體空間中的{n:1},不論你創建多少個變數去賦值堆記憶體中始只存在一個{n:1};我們姑且稱呼這個對象為A,草圖如下:

 

 

 

 

 

 

 

2. 接下來我們可以看到此題中有標註‘關鍵代碼’字樣的,他們考察了我們連續賦值,並且還有屬性操作:

a.x = a = {n:2};

 

js的賦值運算順序永遠都是從右往左的,不過由於“.”是優先順序最高的運算符,所以這行代碼先“計算”了a.x。

 

所以我們先進行屬性操作,a.x,因為此時x作為a的一個屬性,沒有最開始沒有從右向左賦值時它的值為undefined,這行代碼可以說已經執行了a.x,這時如下圖

 

 

接下來從右向左開始賦值,將a的指向從對象A指向了對象B{n:2},

接下來繼續執行 a.x=a,很多人會認為這裡是“對象B也新增了一個屬性x,並指向對象B自己”,很多人這樣認為是錯誤的,根據優先性( .  運算符最先計算),咱們剛纔已經計算過a. x,那時變數a的指向還是對象A,變數a指針並沒有發生變化,所以此時a.x確切地說應該是對象A.x,代碼再次執行時,指針發生了變化,a的指針指向B,此時a.x=a再賦值時不再次執行依次a.x然後再賦值,這樣系統不允許,而是直接賦值,相當於之前的A.x賦值,所以 a.x=a 應理解為對象A的屬性x指向了對象B:

 

那麼根據圖表很容易得出結果當console.log(a.x)的時候,a是指向對象B的,但對象B沒有屬性x。沒關係,當查找一個對象的屬性時,JavaScript 會向上遍歷原型鏈,直到找到給定名稱的屬性為止。但當查找到達原型鏈的頂部 - 也就是 Object.prototype - 仍然沒有找到指定的屬性B.prototype.x,自然也就輸出undefined;

而在console.log(b.x)的時候,由於b.x表示對象A的x屬性,該屬性是指向對象B,自然也輸出了[object Object]了,註意這裡的[object Object]可不是2個對象的意思,對象的字元串形式,是隱式調用了Object對象的toString()方法,形式是:"[object Object]"。

為了驗證咱們的結果我們可以將上面的題進行變種:

1 <script>
2     var a={n:1};
3     var b=a;
4     a={n:2}
5     a.x=a;
6     console.log(a.x);//[object,Object]
7     console.log(b.x);//undefined

8 </script>

  那麼與上題的區別就是我們將變數a指針先改變,然後在進行對象屬性的操作a.x。

嘿嘿,如果我們這樣連等呢?

1 <script>
2     var a={n:1};
3     var b=a;
4     a=a.x={n:2};
5     console.log(a.x);
6     console.log(b.x);
7     console.log(a.n);
8     console.log(b.n);
9 </script>

 

 

此時的結果是和第一題的解題思路是一樣的,只要是既有變數和變數屬性的連等賦值的列印元素屬性的值都為undefined

總結:所以我們做此類題時無外乎考慮這幾個知識點連等賦值的優先順序別從右向左,不過遇見屬性一切玩完,

 我驗證了一下凡是類似於這樣變數a=a.x=引用數據類型,都可以引用只要是既有變數和變數屬性的連等賦值的列印元素屬性的值都為undefined。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一個開發者,如何才能更值錢? 答案非常簡單:掌握稀缺資源。 那麼,怎樣才能持續不斷地掌握稀缺資源,讓自己更值錢呢? 請看接下來介紹的 2 種識別稀缺的方法和 2 種培養稀缺的策略。 稀缺資源的秘密 資源有很多,比如知識、技能、關係、社會資源、信息、天賦等等,哪種資源才是稀缺的呢? 答案可能不在資源本 ...
  • 頁面報錯: 後臺錯誤: Field error in object 'user' on field 'birthday': rejected value [2013-06-24]; codes [typeMismatch.user.birthday,typeMismatch.birthday,typ ...
  • 一、定義 ArrayList和LinkedList是兩個集合類,用於儲存一系列的對象引用(references)。 引用的格式分別為: 1 ArrayList<String> list = new ArrayList<String>(); 1 LinkedList<Integer> list = n ...
  • 很多項目都配置了日誌記錄的功能,但是,卻只有很少的項目組會經常去看日誌。原因就是日誌文件生成規則設置不合理,將嚴重的錯誤日誌跟普通的錯誤日誌混在一起,分析起來很麻煩。 其實,我們想要的一個日誌系統核心就這2個要求: 這樣的日誌系統最大的好處就是可以幫助我們一目瞭然的發現嚴重錯誤。結合管理員後臺直接訪 ...
  • 在開發 H5 應用的時候碰到一個問題,應用只需要一張小的縮略圖,而用戶用手機上傳的確是一張大圖,手機攝像機拍的圖片好幾 M,這可要浪費很多流量。 像我這麼為用戶著想的程式員,絕對不會讓這種事情發生的,於是就有了本文。 獲取圖片 通過 File API 獲取圖片。 預覽圖片 使用 createObje ...
  • 英文:Aurélien Hervé 譯文:眾成翻譯/msmailcode 這裡有一些 Javascript初學者應該知道的技巧和陷阱。如果你已經是專家了,順便溫習一下。 Javascript也只不過是一種編程語言。怎麼可能出錯嘛? 1. 你有沒有嘗試給一組數字排序? Javascript 的sort ...
  • 英文:Ben Northrop 譯文:開源中國 【導讀】:Ben Northrop 在 2016 年滿了 40 歲,本文是他對職業生涯的思考。他認為從長遠來看,應該多投資一些不容易過期、衰竭期較長的知識領域中。 我是一名程式員,幾個月前剛過完 40 歲生日。某個星期六的早晨,我參加了一個 React ...
  • 1,原型:$watch: function(watchExp, listener, objectEquality, prettyPrintExpression){}; 2,參數:watchExp(必須):{(function()|string)},可以字元串表達式,也可以帶當前scope為參數的函數 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...