一個關於對象引用的bug引起的對於引用類型及數組的簡單思考

這兩天本身在寫代碼的時候,出現一個BUG,代碼以下:javascript

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高級程序設計:java

知識梳理


javascript變量的數據類型:

1:基礎類型 : Undefined、null、Boolean、Number和String
2:引用類型 : object數組

其中引用類型的賦值操做須要注意,由於引用類型的值是按引用訪問的,且具備動態屬性,會根據取得其引用的變量的操做而改變該引用的內存對象發生改變。取複製變量的例子用圖示的方法來解釋:
以下代碼:dom

var num1 = 5
    var num2 = num1

基本類型的賦值就至關於建立一個num1的副本,同時將num2的值等於該副本,兩個變量之間的操做互不影響。
圖示以下:
圖片描述函數

而對於引用類型的複製可不是這樣this

var num1 = obj1
    var num2 = num1

這個複製只是將num1的引用賦值給num2,兩者是屬於同一個引用,訪問的都是堆內存中的同一個對象,任何一個該引用的變量發生變化,會對其他使用該引用的變量也發生變化。
圖片描述spa

函數參數的傳參

在JS中函數參數的傳參方式都是按值傳參的
能夠近似當作函數內部聲明一個局部變量名爲參數名字的變量,同時爲其賦值爲參數的值,參數爲引用類型則較爲複雜些,主要是按值傳遞比較難理解。設計

傳遞的參數爲引用類型的話,即函數內部該參數發生了改變會引發堆內存對象的屬性發生改變,那麼爲何不叫按引用訪問,資料中有以下代碼進行解釋:code

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

相關文章
相關標籤/搜索