ECMAScirpt 变量有两种不同的数据类型:基本类型引用类型

基本的数据类型有:undefinedbooleannumberstringnull. 基本类型的访问是按值访问的,就是说你可以操作保存在变量中的实际的值。JavaScript中除了上面的基本类型之外就是引用类型了。

区别如下:
基本类型:

  • 佔用空间固定,保存在栈中
  • 保存与复製的是本身
  • 使用typeof检测数据类型
  • 值类型

引用类型:

基本类型是不会改变,衹能重新赋值,而引用类型值是可以改变的

var a = '123456789',
      b = a;
 
a = '321';
console.log(a) // 321
console.log(b) // 123456789

上面因為是把值保存在了变量了 而不是保存的是引用地址,所以他们两个是相对独立的整体,互不影响。但是如果换成引用类型的话

var a = {
    n: '123456789'
},
b = a;

a.n ='321';
console.log(a) // { n: '321' }
console.log(b) // { n: '321' }

原因在於在javascript语言中创建的对象值中其保存的是对象的引用(也就是一个地址.引用类型值保存在内存中,而JS是不能直接访问内存的,所以对於引用类型,操作的不是实际的对象而是对象的引用。)

这里有个小提示説一下,假如两个相同的基本类型或引用类型(内容一样)相比,看看结果是怎样的?

var base1 = '123',
    base2 = '123',
    obj1 = { a: '123' },
    obj2 = { a: '123' };

console.log(base1 === base2) // true
console.log(obj1 === obj2) // false

如果你还错了那就证明你没理解透上面的东西了,因为前面是值之间直接比较,后面是指向地址的比较,即使两个引用类型看起来一样,衹要不是同一个声明变量,它们就一定不同。

知识一:基本类型值就是简单的数据段;引用类型值保存的是对象的引用,不是实际的对象。

但是在函数中的对象传值又是不是同一回事呢?看看下面代码

function setName(obj) {
    obj.name = '1';
    obj = {};
    obj.name = '2';
}

var obj = {};
setName(obj);

console.log('最终结果obj:', obj) // 最终结果obj: { name: '1' }

没错,结果出乎意料的是1.而不是大多数人刚开始认为的2.
接下来我们在一步步分析出在函数过程中对象发生了什么样的变化?稍微修改下对象名便於区分。

function setName(innerObj) {
    console.log('初始的innerObj:', innerObj); // 初始的innerObj: {}

    innerObj.name = '1';
    console.log('第一次设置属性值的innerObj:', innerObj); // 第一次设置属性值的innerObj: { name: '1' }

    //保存下原对象
    var _innerObj = innerObj;

    innerObj = {};
    console.log('重新赋值的innerObj:', innerObj); // 重新赋值的innerObj: {}

    innerObj.name = '2';
    console.log('第二次设置属性值的innerObj:', innerObj); // 第二次设置属性值的innerObj: { name: '2' }

    console.log('两者之间是不是同一个对象?:', _innerObj == innerObj) // 两者之间是不是同一个对象?: false
    console.log('innerObj:', innerObj) // innerObj: { name: '2' }
    console.log('_innerObj: ', _innerObj) // _innerObj:  { name: '1' }
}

var outerObj = {};
setName(outerObj);
console.log('最终结果outerObj:', outerObj) // 最终结果outerObj: { name: '1' }

过程中可以看出在函数中间 innerObj = {} 之后;对象的指向就已经变了,也就是说这里相当於重新建立一个新的指向,后续的操作都是基於新指向之上进行的。
此时,outerObj === _innerObj !== innerObj, 所以最终输出的是1而不是2.

如果还有些混乱的同学,看看如果不通过函数直接修改会是什么结果?

var obj = {'a':1}
obj = {};
obj = {'a':2};
console.log(obj) // { a: 2 }

这次确确实实的是输出2了。

知识二:JS中所有函数传参都是按值传递的。

Afterward
621 声望62 粉丝

努力去做,对的坚持,静待结果