一个关于对象引用的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

相关文章
相关标签/搜索