本文最后更新于:2020年11月3日 凌晨
变量 原始值和引用值 ECMAScript 变量可以包含两种不同类型的数据:原始值和引用值;
在把一个值赋给变量时,JavaScript 引擎必须确定这个值是原始值还是引用值;
原始值(primitive value)就是最简单的数据;
6 种原始值:Undefined、Null、Boolean、Number、String 和 Symbol;
保存原始值的变量是按值(by value)访问的;
引用值(reference value)则是由多个值构成的对象;
引用值是保存在内存中的对象;因为JS不允许直接访问内存位置,因此不能直接操作对象所在的内存空间;
在操作对象时,实际上操作的是对该对象的引用(reference)而非实际的对象本身;
保存引用值的变量是按引用(by reference)访问的;
动态属性 原始值和引用值的定义方式很类似,都是创建一个变量,然后给它赋一个值;
但是对于引用值而言,可以随时添加、修改和删除其属性和方法;
1 2 3 let person = new Object (); person.name = "Nicholas" ; console .log (person.name );
但是原始值不能有属性,虽然添加属性不会报错;
原始类型的初始化可以只使用原始字面量形式;
1 2 3 let name = "Nicholas" ; name.age = 27 ; console .log (name.age );
当原始类型使用了new
关键字,则JS会创建一个Object类型的实例,但其行为类型原始值:
1 2 3 4 5 6 7 8 let name1 = "Nicholas" ; let name2 = new String ("Matt" ); name1.age = 27 ; name2.age = 26 ; console .log (name1.age ); console .log (name2.age ); console .log (typeof name1); console .log (typeof name2);
复制值 除了存储方式不同,原始值和引用值在通过变量复制时也有所不同;
1 2 3 4 5 6 7 8 9 10 11 let num = 5 ;let num_2 = num;let obj1 = new Object (); let obj2 = obj1; obj1.name = "Nicholas" ; console .log (obj2.name );
传递参数 ECMAScript 中所有函数的参数都是按值传递的;
如果是原始值,那么就跟原始值变量的复制一样,如果是引用值,那么就跟引用值变量的复制一样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function addTen (num ) { num += 10 ; return num; } let count = 20 ;let result = addTen (count); console .log (count); console .log (result); function setName (obj ) { obj.name = "Nicholas" ; } let person = new Object (); setName (person); console .log (person.name );
首先在这里我们能在函数内部修改到外部的对象的属性,这里并不是按引用传递;
这里查阅资料之后发现,有一种按共享传递(call by sharing):调用函数传参时,函数接受对象实参引用的副本 (既不是按值传递的对象副本,也不是按引用传递的隐式引用);
在函数传入对象的时候传入的是对象的地址副本 ,修改了形参的属性可以间接修改了外部的对象的属性,当我们在函数内部重新给形参赋值时候却是不成功的,在函数内部被重写时,而且该函数的形参都是局部作用域,它变成了一个指向本地对象的指针。而那个本地对象在函数执行结束时就被销毁了
1 2 3 4 5 6 7 8 function setName (obj ) { obj.name = "Nicholas" ; obj = new Object (); obj.name = "Greg" ; } let person = new Object (); setName (person); console .log (person.name );
确定类型 前面提出了使用typeof
操作符可以判断数据类型是不是原始类型,字符串,数值,布尔值,或者undefined,但是值如果是对象或者null,那么都会返回object;
1 2 3 4 5 6 7 8 9 10 11 12 let s = "Nicholas" ; let b = true ; let i = 22 ; let u; let n = null ; let o = new Object (); console .log (typeof s); console .log (typeof i); console .log (typeof b); console .log (typeof u); console .log (typeof n); console .log (typeof o);
typeof 虽然对原始值很有用,但它对引用值的用处不大, 我们可以使用instanceof
判断具体是什么类型的对象:
1 2 3 4 5 6 7 result = variable instanceof constructorconsole .log (person instanceof Object ); console .log (colors instanceof Array ); console .log (pattern instanceof RegExp );
按照定义,所有引用值都是 Object 的实例,因此通过 instanceof 操作符检测任何引用值和Object 构造函数都会返回 true(比如数组, 正则, 函数等)。
如果用 instanceof 检测原始值,则始终会返回 false,因为原始值不是对象。
1 2 3 4 5 6 7 8 let a = function ( ) { return ; }console .log (typeof a); console .log (a instanceof Object ) console .log (a instanceof Function )