有了 Javascript,页面才是活的。

活的页面有两个关键要素:有状态、可操作

比如 To-Do List 的例子,状态记录已经添加的待办事项,操作定义添加行为。


javascript 变量 双引号 js变量引用_引用类型

Javascript To-Do List


状态和操作,对应到 JS 语言中,就是变量函数。函数留待下篇讲,今天说说变量

1、类型

JS 中常用的变量类型有:数字(number)、字符串(string)、布尔值(boolean)、对象(object)、数组(array),我们来看一下它们长什么样

  • number:10.1
  • string:'前端同学', '1'
  • boolean:truefalse
  • object:{name: 'Jim', age: 18}
  • array:['Jim', 'Gakki', 'Jim junior']

可以看到,number,string,boolean的结构比较简单,object和array还有内部结构。前者为 JS 中的基本类型,后者为引用类型

那么基本类型和引用类型有什么区别呢?

先来看一个图,一瓶药有两个地方可以写药品说明:一是瓶身上,二是说明书。瓶身上篇幅有限,所以只会写一些简单介绍。不良反应之类占地方的一般会放到说明书中:


javascript 变量 双引号 js变量引用_赋值_02

Javascript 引用类型

JS 为了读取效率,也将变量存储分为类似的索引区(栈 stack)和存储区(堆 heap)。

  • 基本类型(number,string,boolean)结构简单,直接存储在栈里。如上图中的适应症状生产厂商用法用量
  • 引用类型(object,array)在栈里只存储索引地址,指向本体在堆中的真正位置。就像上图中的成分不良反应

我们来尝试将上图中的药品说明变成变量:

  • 适应症状(string): 'js快速上手'
  • 生产厂商(string):'前端同学'
  • 用法用量(number): 1
  • 成分(array): ['变量', '语句', '函数', 'DOM操作', '事件', '异步请求', 'HTTP协议']
  • 不良反应(object):{ englishPoor: 0.8, lazybones: 0.5 }

2、使用

2.1、初始化


/* let是 JS 初始化变量的内置命令 */  

let name = 'Jim';
let age = 18;
let isHandsome = true;
let habits = ['movie', 'fishing', 'swim'];
let score = {chinese: 60, mathmatics: 99, english: 80};

habits[0] // 数组第0项:movie
score.english // 对象属性:80


在页面 右击 -> 检查,打开 Chrome 开发者工具,切换到 console tab,把上面的代码贴入执行,看看执行结果

2.2、比较

JS 中,使用===比较是否相等;基础类型比较值,引用类型比较引用地址


let ageOfJim = 18;
let ageOfGakki = 18;
let habitsOfJim = ['movie', 'fishing', 'swim'];
let habitsOfGakki = ['movie', 'fishing', 'swim'];

ageOfJim === ageOfGakki // true
habitsOfJim === habitsOfGakki // false


你可能会奇怪,为什么 habits 变量不相等,我们把这几个变量的存储方式画个图就明白了:


javascript 变量 双引号 js变量引用_赋值_03

Javascript 堆栈

可以看到,在 JS 中初始化对象,引用类型都会在堆中分配一块新的存储块,栈中只有该存储块的地址标识。由于引用类型比较引用地址,所以两个 habits 变量并不相等

2.3、赋值

那假如来了一位新同学 Tom,他的兴趣和 Gakki 相同,我们可以简单的进行赋值操作


let habitsOfTom = habitsOfGakki;


这么赋值后,内存中变成这样:


javascript 变量 双引号 js变量引用_引用js_04

Javscript 引用赋值

可以看到,赋值操作和初始化不同,并没有在堆中创建新的内存块,而是直接吧引用地址复制给了新变量,指向同一个堆对象

2.4、作用域

变量的作用域就是其有效范围,我们来看一段代码


// console.log 的作用是输出变量值

let a = 1;
if(true) {
  let b = 2
  console.log(a) // 1
  console.log(b); // 2
}

console.log(a) // 1
console.log(b) // b is not defined


可以看到,变量a是全局都读取得到,而b只有在if语句内才有效。

简单的说,变量的作用域就是一个花括号的范围,在花括号内定义的,只有在花括号内才有效,出了就不认了。

3、总结

本篇介绍了 Javascript 语言两大基础变量与函数之一的变量,重点介绍了引用类型,要牢记引用类型的存储方式,这对后续理解函数也有莫大作用。

我在写作过程中,一直在做取舍:哪些该讲,哪些需要略过,甚至为了便于理解,先不区分李鬼和李逵。总得原则就是抓大放小,理解通畅。