ES6将数据分为两类:原始值和引用值
原始值 表示单一的数据,
ES设计了6种原始值:Undefined、Null、Boolean、Number、String和Symbol(ES6新增,表示独一无二的值,最大的用法是用来定义对象的唯一属性名),保存原始值的变量是按值访问,操作存储在变量内存中的实际值。
引用值 表示由多个值(原始值或引用值)构成的对象
包括Object,function,Array,RegExp,Data,引用值与原始值不同,ES不允许直接访问对象的内存空间。实际操作对象时,访问的是保存对象的内存地址,即该对象的引用。
原始值与引用值具有以下区别:
动态属性
原始值是不可改变的,当你给一个已定义的原始值重新赋值时,实际上会为该原始值分配新的地址返回新的值,而原来的值则等待垃圾回收
引用值(对象)可以随时添加、修改和删除其属性和方法。`
let person = new Object();
person.name = "John";//添加一个值为属性
person.showMe = function () {//添加一个函数为方法
console.log("Hi, I'm " + this.name);
};
原始值不能有属性
let one = "Tom";
one.age = 20;//等于new string(one),添加age属性,实例在此处使用完就销毁
console.log(one, one.age);//"Tom",undefined
值传递
原始值与引用值传递在本质上没有区别,都是将一个变量中保存的信息复制给另一个变量
原始值传递的是值,传递进来的参数是一个副本(拷贝),而不是传递进来参数本身,所以对值传递参数的修改不会影响到调用方传递的参数对象
let a = 100;
let b = a;
b++;
console.log(a, b);
引用值传递的是引用,传递进来的参数是指向调用方传递的参数本身的。对引用传递的参数的修改会影响到调用方传递的参数对象。
let obj1 = { value: 100 };
let obj2 = obj1;
obj2.value = 200;
console.log(obj1.value, obj2.value);
确定类型
原始值可以使用typeof判断类型,而几乎所有的引用值通过typeof操作符来判断结果都是object,因此对于引用值,typeof的意义不大,通常采用instanceof操作符,判断引用值是否为某个构造函数的实例。
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
语法: object instanceof constructor
object:某个实例对象 constructor:某个构造函数
let obj = new Object();
let a = [1, 2, 3];
console.log(obj instanceof Object);//true
console.log(a instanceof Array);//true
( instanceof 还可以在继承关系中用来判断一个实例是否属于它的父类型)
// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例
function Aoo(){}
function Foo(){}
Foo.prototype = new Aoo();//JavaScript 原型继承
var foo = new Foo();
console.log(foo instanceof Foo)//true
console.log(foo instanceof Aoo)//true
原始值包装类型
为了方便操作原始值,ES提供了3中特殊的引用类型:Boolean、Number和String。
每当用到某个原始值的方法或属性时,后台会创建一个相应的原始值包装类型的对象,从而暴露出操作原始值的各种方法。
let s1 = "hello world";
let s2 = s1.substr(0, 5)
原始值本身不是对象,因此字符串 s1 在逻辑上不应该有 substr() 方法。
而实际上,给s2赋值时s1却使用了这个方法,因为在第二步s1.这里就创造了新的实例
后台实际执行了以下步骤:
(1)创建一个包含了原始值的String类型的实例;
(2)调用实例上的特定方法;
(3)销毁该实例;
let value = "200";
let number = Number(value);//此处number存的是原始值,Number()是转型函数
console.log(typeof number);//"number"
let obj = new Number(value);//new Number()是构造函数
console.log(typeof obj);//"object"
console.log(obj+number);//400,原始值和对象可相加,因为obj会隐性调用valueof()方法获取对象的原始值