摘要:圖示如下而對于引用類型的復制可不是這樣這個復制只是將的引用賦值給,二者是屬于同一個引用,訪問的都是堆內存中的同一個對象,任何一個該引用的變量發生變化,會對其余使用該引用的變量也發生變化。
這兩天自己在寫代碼的時候,出現一個BUG,代碼如下:
class Car { constructor(carId) { this.position = [114, 130] this.path = [] this.speed = Math.floor(Math.random() * 5) this.timer = null } run(){ this.position[0] += this.speed * (Math.random() * 2 == 1 ? 1 : -1) this.position[1] += this.speed * (Math.random() * 2 == 1 ? 1 : -1) this.path.push(this.position) if(this.path.length > 10){ this.path.shift() } } start(){ this.timer = setInterval(function(){ this.run() }, 1000) } stop(){ clearInterval(this.timer) } } var car = new Car("10086") car.start()
代碼預期的結果是,記錄car的最近10個坐標點。
但是實際結果大失所望,得出的是10個一模一樣的坐標點,原因在于調用run方法時,其中坐標的改變是基于其屬性position這個數組對象的改變,而數組對象的變量名其實是對數組對象地址的引用,因此導致了最后一個坐標的改變引起了所有坐標的改變。
通過這個BUG對自己的基礎知識又進行了一次梳理,歸納以及總結,參考資料為JavaScript高級程序設計:
1:基礎類型 : Undefined、null、Boolean、Number和String
2:引用類型 : object
其中引用類型的賦值操作需要注意,因為引用類型的值是按引用訪問的,且具有動態屬性,會根據取得其引用的變量的操作而改變該引用的內存對象發生改變。取復制變量的例子用圖示的方法來解釋:
如下代碼:
var num1 = 5 var num2 = num1
基本類型的賦值就相當于創建一個num1的副本,同時將num2的值等于該副本,兩個變量之間的操作互不影響。
圖示如下:
而對于引用類型的復制可不是這樣
var num1 = obj1 var num2 = num1
這個復制只是將num1的引用賦值給num2,二者是屬于同一個引用,訪問的都是堆內存中的同一個對象,任何一個該引用的變量發生變化,會對其余使用該引用的變量也發生變化。
在JS中函數參數的傳參方式都是按值傳參的
可以近似看成函數內部聲明一個局部變量名為參數名字的變量,同時為其賦值為參數的值,參數為引用類型則較為復雜些,主要是按值傳遞比較難理解。
傳遞的參數為引用類型的話,即函數內部該參數發生了改變會引起堆內存對象的屬性發生改變,那么為什么不叫按引用訪問,資料中有如下代碼進行解釋:
function setName(obj) { obj.name = "Nicholas"; obj = new Object(); obj.name = "Greg"; } var person = new Object(); setName(person); alert(person.name); //"Nicholas"
書中的解釋比較簡潔,個人理解為如果是按引用傳參則會發生堆內存的對象會發生改變,由原本的實例person將被新的new Object的實例,同時將其屬性name置為"Greg",即最終obj指向的是new Object的實例,而事實上沒有,可以理解為函數的引用類型的參數為引用類型的引用,且這里對引用的處理方式是類似基本類型的值一般,不會發生變化。
圖示如下:
歸納總結基礎知識梳理完畢,回到我的BUG,犯的錯誤就是引用類型的訪問方式的錯誤,path所push的position數組準確來說指向的都是同一個對象,因此position的每次變化,數組中所有的元素都會發生相同的變化,導致path數組的元素均為一致.
為此對數組的方法進行一次歸納,將數組中可以返回新數組副本(即對原數組無影響)的方法,以方便避免像我這種使用導致的BUG
返回新數組副本方法:concat, slice, splice, filter, map
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90560.html
摘要:但在開始之前應該心中有數值的不可變性并不是說我們不能在程序編寫時不改變某個值。這些都是對值的不可變這個概念的誤解。程序的其他部分不會影響的賦值。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌著滬江血液的純粹工程:認真,是 HTML 最堅實的梁柱;分享,是 CSS 里最閃...
摘要:項目中異常分析引發崩潰日志的流程分析解決辦法常見的出現場景狀態異常非法線程操作。引發崩潰日志的流程分析解釋如下所示,釋放與此位圖關聯的本機對象,并清除對像素數據的引用。 目錄介紹 1.1 java.lang.UnsatisfiedLinkError找不到so庫異常 1.2 java.lang.IllegalStateException非法狀態異常 1.3 android.conten...
摘要:幸運的是,使用符號創建的構造器,如果在不使用來調用,則始終會報錯,即使在非嚴格模式下也不會產生問題。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Bugs and Errors 譯者:飛龍 協議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《JavaScript 編程精解(第 2 版)》 調試的難度是開始編寫代碼的兩倍。 因此,如...
摘要:但是當傳遞的參數為對象或者數組的時候,是通過引用傳入的,所以對于一個引用類型的來說,在子組件中改變這個參數本身將會影響到父組件的數據狀態。 問題 父級組件與子組件的通信一般都是通過props來實現的,因為數據流向的單一才能保證數據變化的可追蹤性,在vue中props遵循的是單向數據流,原則上子組件修改props是不被允許的。但是當props傳遞的參數為對象或者數組的時候,是通過引用傳入...
摘要:出現錯誤引發崩潰日志的流程分析這個錯誤是應用的方法總數限制造成的。 目錄介紹 1.1 java.lang.ClassNotFoundException類找不到異常 1.2 java.util.concurrent.TimeoutException連接超時崩潰 1.3 java.lang.NumberFormatException格式轉化錯誤 1.4 java.lang.Illegal...
閱讀 3543·2021-11-22 15:22
閱讀 3333·2019-08-30 15:54
閱讀 2729·2019-08-30 15:53
閱讀 816·2019-08-29 11:22
閱讀 3538·2019-08-29 11:14
閱讀 2077·2019-08-26 13:46
閱讀 2217·2019-08-26 13:24
閱讀 2280·2019-08-26 12:22