精华内容
下载资源
问答
  • 当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值 基本数据类型:数字(Number)、字符串(String)、布尔(Boolean)、空(Null)、未定义(Undefined) 引用数据类型:也就是...
  • 前两天看到kraaas大神的关于基本数据类型和引用类型区别的文章觉得写得非常不错,就想着在其基础上加上自己平时看到的一些知识点理解,所以就有了以下的文章 js基本数据类型包括:undefined,null,number,boolean...
  • JS基本类型和引用类型区别主要以下几个方面: 在内存中的位置不同 基本类型: 占用空间固定,保存在栈中; 引用类型:占用空间不固定,保存在堆中; **栈(stack)**为自动分配的内存空间,它由系统自动释放;...

    JS基本类型和引用类型的区别主要以下几个方面:

    • 在内存中的位置不同
    • 基本类型: 占用空间固定,保存在栈中;
    • 引用类型:占用空间不固定,保存在堆中;

    **栈(stack)**为自动分配的内存空间,它由系统自动释放;使用一级缓存,被调用时通常处于存储空间中,调用后被立即释放。
    **堆(heap)**则是动态分配的内存,大小不定也不会自动释放。使用二级缓存,生命周期与虚拟机的GC算法有关

    当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;栈中存储的是基础变量以及一些对象的引用变量,基础变量的值是存储在栈中,而引用变量存储在栈中的是指向堆中的数组或者对象的地址,这就是为何修改引用类型总会影响到其他指向这个地址的引用变量。

    当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

    • 赋值、浅拷贝、深拷贝

    • 对于基本类型值:赋值、浅拷贝、深拷贝时都是复制基本类型的值给新的变量,之后二个变量之间操作不在相互影响。

    • 对于引用类型值,

    赋值后二个变量指向同一个地址,一个变量改变时,另一个也同样改变;

    浅拷贝后得到一个新的变量,这个与之前的已经不是指向同一个变量,改变时不会使原数据中的基本类型一同改变,但会改变会原数据中的引用类型数据

    深拷贝后得到的是一个新的变量,她的改变不会影响元数据

    -和源数据是否指向同一对象第一层数据为基本数据类型原数据中包含子对象
    赋值改变会使原数据一同改变改变会使原数据一同改变
    浅拷贝改变不会使原数据一同改变改变会使原数据一同改变
    深拷贝改变不会使原数据一同改变改变不会使原数据一同改变

    代码为:

      var obj1 = {
            'name' : 'zhangsan',
            'age' :  '18',
            'language' : [1,[2,3],[4,5]],
        };
    
        var obj2 = obj1;
    
    
        var obj3 = shallowCopy(obj1);
        function shallowCopy(src) {
            var dst = {};
            for (var prop in src) {
                if (src.hasOwnProperty(prop)) {
                    dst[prop] = src[prop];
                }
            }
            return dst;
        }
    
        obj2.name = "lisi";
        obj3.age = "20";
    
        obj2.language[1] = ["二","三"];
        obj3.language[2] = ["四","五"];
    
        console.log(obj1);  
        //obj1 = {
        //    'name' : 'lisi',
        //    'age' :  '18',
        //    'language' : [1,["二","三"],["四","五"]],
        //};
    
        console.log(obj2);
        //obj2 = {
        //    'name' : 'lisi',
        //    'age' :  '18',
        //    'language' : [1,["二","三"],["四","五"]],
        //};
    
        console.log(obj3);
        //obj3 = {
        //    'name' : 'zhangsan',
        //    'age' :  '20',
        //    'language' : [1,["二","三"],["四","五"]],
        //};
        ```
    2.1、**浅拷贝**
    数组常用的浅拷贝方法有`slice,concat,Array.from() ,以及es6`的析构
    
    ```js
    
    
    var arr1 = [1, 2,{a:1,b:2,c:3,d:4}];
    var arr2 = arr1.slice();
    var arr3 = arr1.concat();
    var arr4 = Array.from(arr1);
    var arr5 = [...arr1];
    arr2[0]=2;
    arr2[2].a=2;
    arr3[0]=3;
    arr3[2].b=3;
    arr4[0]=4;
    arr4[2].c=4;
    arr5[0]=5;
    arr5[2].d=5;
    // arr1[1,2,{a:2,b:3,c:4,d:5}]
    // arr2[2,2,{a:2,b:3,c:4,d:5}]
    // arr3[3,2,{a:2,b:3,c:4,d:5}]
    // arr4[4,2,{a:2,b:3,c:4,d:5}]
    // arr5[5,2,{a:2,b:3,c:4,d:5}]
    

    对象常用的浅拷贝方法Object.assign(),es6析构

    
    var obj1 = {
        x: 1, 
        y: {
            m: 1
        }
    };
    var obj2 = Object.assign({}, obj1);
    console.log(obj1) //{x: 1, y: {m: 1}}
    console.log(obj2) //{x: 1, y: {m: 1}}
    obj2.x=2;
    obj2.y.m = 2; //修改obj2.y.m
    console.log(obj1) //{x: 1, y: {m: 2}}
    console.log(obj2) //{x: 2, y: {m: 2}}
    

    我们自己实现一个浅拷贝

    
    var obj = { a:1, arr: [2,3] };
    var shallowObj = shallowCopy(obj);
    
    var shallowCopy = function(obj) {
        // 只拷贝对象
        if (typeof obj !== 'object') return;
        // 根据obj的类型判断是新建一个数组还是对象
        var newObj = obj instanceof Array ? [] : {};
        // 遍历obj,并且判断是obj的属性才拷贝
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = obj[key];
            }
        }
        return newObj;
    }
    

    2.2、深拷贝
    比较简单粗暴的的做法是使用JSON.parse(JSON.stringify(obj))

    
    var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}]
    var new_arr = JSON.parse( JSON.stringify(arr) );
    new_arr[4].old=4;
    console.log(arr); //['old', 1, true, ['old1', 'old2'], {old: 1}]
    console.log(new_arr); //['old', 1, true, ['old1', 'old2'], {old: 4}]
    

    JSON.parse(JSON.stringify(obj))看起来很不错,不过MDN文档 的描述有句话写的很清楚:

    undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。
    但是在平时的开发中JSON.parse(JSON.stringify(obj))已经满足90%的使用场景了。
    下面我们自己来实现一个

    
    var deepCopy = function(obj) {
        if (typeof obj !== 'object') return;
        var newObj = obj instanceof Array ? [] : {};
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
            }
        }
        return newObj;
    }
    

    总结:
    在这里插入图片描述

    展开全文
  • 主要介绍了JavaScript基本类型和引用类型,基本类型中还包含了类型转换,感兴趣的小伙伴们可以参考一下
  • 基本类型和引用类型 ECMAScript包含两个不同类型的值:基本类型和引用类型值。基本类型值指的是简单的数据段;引用类型值指由多个值构成的对象。当我们把变量赋值给一个变量时,解析器首先要做的就是确认这个值是...
  • 查阅了相关博客:Java 浅拷贝深拷贝的理解实现方式,发现要理解浅拷贝深拷贝的区别,重点还是要理解基本数据类型和引用数据类型的复制过程区别。 splice()方法介绍:该方法返回一个新的数组对象,这一对象是一...

    前天刚学完Javascript基础语法,现在对知识点进行梳理,当梳理到数组的常用方法中的splice()方法时,里面提到了浅拷贝的概念。查阅了相关博客:Java 浅拷贝和深拷贝的理解和实现方式,发现要理解浅拷贝和深拷贝的区别,重点还是要理解基本数据类型和引用数据类型的复制过程区别。

    splice()方法介绍:该方法返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)决定的原数组的浅拷贝。原始数组不会被改变。MDN官网资料:Array.slice()

    Javascript基本数据类型和引用数据类型的区别和注意点

    区别

    区别1:基本数据类型的数据值存储在栈内存中,引用数据类型的数据值存储在堆内存中
    基本数据类型的数据值存储在栈内存中,变量指向这块栈内存的数据值。通过变量找到这个数据值,只需要一步。

    引用数据类型不仅有数据值,还有一个专门指向这个数据值的地址值(理解为这个数据值的地址管家),并且数据值存储在堆内存中,地址值存储在栈内存中。变量指向地址值,而地址值指向堆内存中的数据值。而通过变量找到这个存储在堆内存中的数据值,需要两步。

    在这里插入图片描述
    区别2:变量复制时,基本数据类型复制的是数据值,引用数据类型复制的是地址值
    基本数据类型的变量复制时,复制的是变量的数据值

    引用数据类型的变量复制时,复制的是变量的指向堆内存中数据值的地址值。两个相同的地址值,指向同一块堆内存中的数据值。

    代码用JavaScript编写
    基本数据类型变量复制代码:

    var num1 = 10;
    //将num1的值复制给num2
    var num2 = num1;
    //复制后,改变num1的值
    num1 = 20;
    //打印num1和num2,看改变num1的值,是否会影响到num2
    console.log(num1, num2);
    

    代码运行结果:

    引用数据类型变量复制代码:

    var person1 = {
                name: "张三",
                age: 18,
                sayHi: function f() {
                    console.log(this.name + 'say: "My name is' + this.name + '"');
                }
            };
    //将person1复制给person2        
    var person2 = person1;
    //复制后,改变person1的数据值
    person1.name = '李四';
    person1.age = 20;
    //看改变person1的数据值,对person2的数据值影响
    console.log(person2.name,person2.age);
    person1.sayHi();
    

    代码运行结果:
    在这里插入图片描述
    基本类型的变量复制过程:首先在栈内存中,开辟一块新的内存空间,然后将变量num1的数据值(10)复制到这块新的栈内存空间中,变量num2指向新的栈内存空间数据值。两个变量指向的数据值互不干扰。
    在这里插入图片描述
    引用类型的变量复制过程:首先在栈内存中,开辟一条新的内存空间,然后将变量person1的地址值!地址值!地址值!(牢记)复制到新的栈内存空间中,使变量person2指向新的栈内存空间中的地址值。两个地址值相同,指向同一块堆内存中的数据值
    在这里插入图片描述

    注意点

    注意点1:
    切记:引用数据类型只有new时,才会在堆内存中开辟新的内存空间
    引申:new的过程,你真的理解了new的过程了吗?

    注意点2:
    java中的String是引用数据类型,而JavaScript中的String类型是基本数据类型,在字符串调用字符串的方法时,系统自动创建一个临时字符串对象,当字符串调用完方法后,临时对象被销毁。

    String类型比较特殊,其值不变性也要引起注意。

    值不变性:改变String类型数据值时,不像其他基本数据类型,在内存中直接修改数据值。而Sting类型修改数据值时,需3步:
    1.首先需要重新开辟一块内存空间,并将原来的数据值复制一份到新的内存空间
    2.然后在新的内存空间中,对数据值进行修改。
    3.将变量指向新的内存空间的数据值。

    原来的内存空间没有了引用,系统会过一段时间将其回收。但具体过多久,就不知道了。所以应该避免大量对String类型数据值的修改。

    注意点3:
    由此引申的知识点:浅拷贝和深拷贝的区别,但只要记住并理解三点,万变不离其宗。1.引用数据类型变量的复制,只是将指向堆内存中的数据值的地址值复制了一份,两个地址值指向同一块堆内存。2.引用数据类型只有new时,才会在堆内存中开辟新的内存空间。3.对String类型数据值的修改,系统会开辟一块内存空间,并将数据值复制给新的内存空间,在新的内存空间中,对复制的数据值进行修改,变量重新指向新内存空间中数据值。具体可参考:Java 浅拷贝和深拷贝的理解和实现方式

    展开全文
  • 1.基础类型 A. 基础类型有5种,Number,String,Boolean,Null,Undefined B. 基础类型没有堆的概念,堆只针对引用类型。 所有基础类型都是以key-value形式存放在栈中,...所有引用类型都是以key-value形式存放在栈中,
  • 这篇文章主要是从内存的角度来区分基本类型和引用类型区别: 1、先了解内存分区(大家需要知道,定义的变量都是在内存中存放的) 内存是存储数据的,不同类型的数据要存储在不同的区域,即分类存放,不同的区域...

    这篇文章主要是从内存的角度来区分基本类型和引用类型的区别:

    1、先了解内存分区(大家需要知道,定义的变量都是在内存中存放的)

             内存是存储数据的,不同类型的数据要存储在不同的区域,即分类存放,不同的区域作用和功能也不一样。就像你家里的衣柜一样,也分了不同的区域:如挂西装的区域,放袜子的区域等等,我相信每个人都会把这两个东西放在不同的区域。要不然,当你西装革履地参加一个高档的宴会,手塞在裤兜里,掏出来一只臭袜子,是不是很尴尬!!!哈哈!!!

    以下为内存的分区图。内存分为四个区域:栈区(堆栈),堆区,全局静态区,只读区(常量区和代码区)。

    栈区里存放的数据:局部变量,形参,被调用函数的地址等等。

    堆区里存放的数据:存放数据:new出来的数据。

    详细去看:https://blog.csdn.net/jiang7701037/article/details/98728249

    2、基本类型(值类型)和引用类型变量分别的内存示意图

    3、引用类型赋值时内存的变化

    4、基本类型(值类型)作为函数的参数的内存变化

    5、引用类型作为函数的参数时,内存的变化

    展开全文
  • 基本类型引用类型。 也有其他的叫法,比如原始类型对象类型,拥有方法的类型不能拥有方法的类型,还可以分为可变类型不可变类型,其实这些叫法都是依据这两种的类型特点来命名的 1.基本类型 基本的数据...

    ECMAScirpt 变量有两种不同的数据类型:

    基本类型,引用类型。

    也有其他的叫法,比如原始类型和对象类型,拥有方法的类型和不能拥有方法的类型,还可以分为可变类型和不可变类型,其实这些叫法都是依据这两种的类型特点来命名的

    1.基本类型

    基本的数据类型有:

    undefined,boolean,number,string,null.

    基本类型的访问是按值访问的,就是说你可以操作保存在变量中的实际的值。


    1.基本类型有以下几个特点

    任何方法都无法改变一个基本类型的值,比如一个字符串:

    var name = 'jozo';
    
    name.toUpperCase();   // 输出 'JOZO'
    console.log(name);    // 输出  'jozo'

    会发现原始的name并未发生改变,而是调用了toUpperCase()方法后返回的是一个新的字符串。


    再来看个:

    var person = 'jozo';
    person.age = 22;
    person.method = function(){//...};
     
    console.log(person.age);    // undefined
    console.log(person.method); // undefined

    通过上面代码可知,我们不能给基本类型添加属性和方法,再次说明基本类型时不可变得;

     

    2.基本类型的比较是值的比较:

    只有在它们的值相等的时候它们才相等。
    但你可能会这样:

    var a = 1;
    var b = true;
    console.log(a == b);  //true

    它们不是相等吗?

    其实这是类型转换和 == 运算符的知识了,也就是说在用==比较两个不同类型的变量时会进行一些类型转换。像上面的比较先会把true。
    转换为数字1再和数字1进行比较,结果就是true了。 这是当比较的两个值的类型不同的时候==运算符会进行类型转换,但是当两个值的类型相同的时候,即使是==也相当于是===。

    var a = 'jozo';
    var b = 'jozo';
    console.log(a === b);//true

     

    3.基本类型的变量是存放在栈区的(栈区指内存里的栈内存)

    假如有以下几个基本类型的变量:

    var name = 'jozo';
    var city = 'guangzhou';
    var age = 22;

    那么它的存储结构如下图:

    栈区包括了 变量的标识符和变量的值。

     

    2.引用类型

    javascript中除了上面的基本类型(number,string,boolean,null,undefined)之外就是引用类型了,也可以说是就是 对象、数组、函数了。对象是属性和方法的集合。
    也就是说引用类型可以拥有属性和方法,属性又可以包含基本类型和引用类型。

    来看看引用类型的一些特性:

    1.引用类型的值是可变的

    我们可为为引用类型添加属性和方法,也可以删除其属性和方法,如:

    var person = {};//创建个控对象 --引用类型
    person.name = 'jozo';
    person.age = 22;
    person.sayName = function(){console.log(person.name);} 
    person.sayName();// 'jozo'
     
    delete person.name; //删除person对象的name属性
    person.sayName(); // undefined

    上面代码说明引用类型可以拥有属性和方法,并且是可以动态改变的。

     

    2.引用类型的值是同时保存在栈内存和堆内存中的对象

    javascript和其他语言不同,其不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,那我们操作啥呢?

    实际上,是操作对象的引用,所以引用类型的值是按引用访问的。
    准确地说,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,也可以说是该对象在堆内存的地址。

    假如有以下几个对象:

    var person1 = {name:'jozo'};
    var person2 = {name:'xiaom'};
    var person3 = {name:'xiaoq'};

    则这三个对象的在内存中保存的情况如下图:

     

    3.引用类型的比较是引用的比较

    var person1 = '{}';
    var person2 = '{}';
    console.log(person1 == person2); // true

    上面讲基本类型的比较的时候提到了当两个比较值的类型相同的时候,相当于是用 === ,所以输出是true了。

    再看看:

    var person1 = {};
    var person2 = {};
    console.log(person1 == person2); // false

    可能你已经看出破绽了,上面比较的是两个字符串,而下面比较的是两个对象,为什么长的一模一样的对象就不相等了呢?

    别忘了,引用类型时按引用访问的,换句话说就是比较两个对象的堆内存中的地址是否相同,那很明显,person1和person2在堆内存中地址是不同的:

    所以这两个是完全不同的对象,所以返回false;

     

    3.简单赋值

    在从一个变量向另一个变量赋值基本类型时,会在该变量上创建一个新值,然后再把该值复制到为新变量分配的位置上:

    var a = 10;
    var b = a;
     
    a ++ ;
    console.log(a); // 11
    console.log(b); // 10

    此时,a中保存的值为 10 ,当使用 a 来初始化 b 时,b 中保存的值也为10,但b中的10与a中的是完全独立的,该值只是a中的值的一个副本,此后,这两个变量可以参加任何操作而相互不受影响。

    也就是说基本类型在赋值操作后,两个变量是相互不受影响的。

     

    4.对象引用

    当从一个变量向另一个变量赋值引用类型的值时,同样也会将存储在变量中的对象的值复制一份放到为新变量分配的空间中。

    前面讲引用类型的时候提到,保存在变量中的是对象在堆内存中的地址,所以,与简单赋值不同,这个值的副本实际上是一个指针,而这个指针指向存储在堆内存的一个对象。

    那么赋值操作后,两个变量都保存了同一个对象地址,则这两个变量指向了同一个对象。

    因此,改变其中任何一个变量,都会相互影响:

    var a = {}; // a保存了一个空对象的实例
    var b = a;  // a和b都指向了这个空对象
     
    a.name = 'jozo';
    console.log(a.name); // 'jozo'
    console.log(b.name); // 'jozo'
     
    b.age = 22;
    console.log(b.age);// 22
    console.log(a.age);// 22
     
    console.log(a == b);// true

    它们的关系如下图:

    因此,引用类型的赋值其实是对象保存在栈区地址指针的赋值,因此两个变量指向同一个对象,任何的操作都会相互影响。

     

     

     

     

     

     

     

    展开全文
  • 主要介绍了JavaScript数据类型之基本类型和引用类型的值,本文讲解了动态的属性、复制变量值、传递参数、检测类型等内容,需要的朋友可以参考下
  • 主要介绍了JavaScript引用类型和基本类型详解的相关资料,需要的朋友可以参考下
  • 跟我学习javascript基本类型和引用类型,利用图解的方式,告诉大家javascript基本类型和引用类型区别和联系,感兴趣的小伙伴们可以参考一下
  • JavaScript基本类型中的数据可以是常量,也可以变量。由于JavaScript采用弱类型的形式,因而一个数据的变量或常量不必首先作声明,而是在使用或赋值时确定其数据的类型的。当然也可以先声明该数据的类型,它是...
  • 基本类型和引用类型,他们是区别是一个有固定空间存在于栈内存中,一个没有固定空间保存在堆内存中并且在栈内存中保存了一个指向实现位置的指针。 市面上很多书都有不小的篇幅在讲。这篇文章会讲几个方面,这些...
  • js中的基本类型和引用类型有哪些,有什么区别?】 每篇分享文从 【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】 八个方面深度解析前端知识/技能,本篇...
  • js中的基本类型和引用类型 1.JavaScript中的变量类型有哪些? (1)基本类型基本类型):字符串(string)、数值(number)、布尔值(boolean)、undefined、null (这5种基本数据类型是按值访问的,因为可以...
  • 主要介绍了Javascript中的基本类型和引用类型的相关资料,包括基本类型和引用类型的概念及区别,数据类型检测给大家详细介绍了js基本类型和引用类型,非常不错,需要的朋友可以参考下
  • JS基本数据类型和引用数据类型区别基本数据类型种类1. Undefined2. Null3. Boolean4. Number5. String6. Symbol特点引用数据类型种类特点浅拷贝深拷贝 JS分两种数据类型基本数据类型和引用数据类型 基本数据类型...
  • JavaScript 基本类型和引用类型区别 变量可存放两种类型的值,基本类型的值(primitive values)和引用类型的值(reference values)。 JavaScript 中共有 6 种基本数据类型(原始数据类型):Null、Undefined、...
  • js基本数据类型:Number、String、Boolean、Null、undefined、Symbol(es6) 引用数据类型:Object 注:数组、函数、正则表达式都是对象。 1、基本数据类型存放在栈中 基本数据类型存放在栈中,数据大小确定,内存空间...
  • JavaScript和ECMAscript的...ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构成的对象。 当我们把变量赋值给一个变量时,解析器...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 160,219
精华内容 64,087
关键字:

js基本类型和引用类型的区别