【JavaScript】(一)发展史、ECMAScript、编程语言、JavaScript、变量、JS的值、栈和堆

293 阅读7分钟

发展史

五大浏览器内核

  • IE - Trident
  • Chrome - WebKit / Blink
  • Safari - WebKit
  • Firefox - Gecko
  • Opera - Preto

浏览器发展史

1990年

蒂姆·博纳斯·李 (超文本分享资讯的人),开发了world wide web 浏览器,后移植到C改名为libwww/nexus

1993年

美国伊利诺大学 NCSA组织(马克·安德森),开发了Mosaic浏览器,一款真正意义上的图形化浏览器。

1994年

马克·安德森吉姆·克拉克(硅图SGI公司成员)成立了公司:Mosaic Communications Corporation(马赛克交流公司)。

后来出了一点小插曲:MOSIAC 商标属于 伊利诺大学,在马克.安德森离开后,被转让给了 Spyglass 公司,所以更名为 Netscape Communication Corporation(网景公司)。

网景公司Mosaic 的基础上开发了 Netscape Navigator 浏览器,流行了将近十年直至2003年。

1996年

  • 微软公司收购了Spyglass公司,通过 Mosaic 开发了 IE(Internet Explorer 1.0),这一年微软发布了 IE3,出现了第一个脚本语言:JScript,可以让用户在网页上进行动态的交互。
  • 网景公司 Brendan Eich(布兰登·艾奇) 在 Netscape Navigator浏览器开发出了 LiveScript(JavaScript的前身),当时Java的热度很高,但网景公司的 LiveScript 不温不火,于是和Sun公司商量,合伙推广和宣传产品,LiveScript 更名为 JavaScript

2001年

  • IE6XP 的诞生,出现了 JS 引擎
  • IE6将渲染引擎汇中解析JavaScript的这一部分剥离出来,形成了引擎

2003年

Mozilla公司推出了Firefox浏览器(基于Netscape Navigator改的

2008年

  • Google 基于 WebKit | Blink 内核 + Gears功能(创造了离线上网的功能)推出了Chrome浏览器。
  • Chrome -> V8引擎(JS引擎)

V8 引擎的优点:

  • 直接翻译机器码
  • 独立于浏览器运行

Node.js是一个基于 Chrome V8 引擎能够独立运行的 JavaScript 环境。

渐进式 WEB APP(PROGRESSIVE WEB APP)

Google公司提出的 Progressive Web App 是一种理念,或者叫打包产品,因为他是把众多能让WEB产品APP化的能力的一个集合。

Progressive Web App的三大基本能力:

  • 类APP交互
  • 消息推送
  • 离线缓存

2009年

甲骨文Oracle公司收购Sun公司,JavaScript的所有权给了Oracle公司。

ECMAScript

  • 全称(European Computer Manufacturers Association) 欧洲计算机制造商协会
  • 评估、开发、认可电信/计算机标准
  • 里面有很多标准清单,其中ECMA-262就是脚本语言的规范(ECMAScript)
  • ECMAScript是用来规范化脚本语言的

为了让最初的JavaScript与最初的JScript能遵循同一套标准发展而诞生的ECMAScript,正好排到了作为ECMA的262号标准而已,所以得到ECMA-262编号。

编程语言

编程语言的分类

编程语言分为 编译型解释型

编译过程

编译型:源码 => 编译器 => 机器语言 => 可执行文件

解释型:源码 => 解释器 => 解释一行执行一行

优缺点

解释型语言 => 不需要根据不同的系统平台进行移植,只要系统里有相应的解释器就一定能够执行。

编译型语言 => 跨平台性不好,更适合复杂的、逻辑性较强的程序,这样运算速度会更快一些,更有优势。

脚本语言

脚本语言通过 脚本引擎解释器 才能正常运行。

前后端都有脚本语言:

  • JS/JScript/VBScript/ActionScript => 客户端脚本

    • JS的解释器在浏览器JS引擎上,JScript微软只能在IE上运行
  • php/asp => 服务器端脚本

    • 解释器在服务端上,所以页面看不到解释的过程。

JavaScript

JS的三大块

  • ECMAScript
    • 语法、变量、关键字、保留字、值、原始类型、引用类型、对象、函数、继承。
  • DOM
    • W3C规范,操作HTML文档,获取、添加、删除、修改HTML元素。
  • BOM
    • 没有规范,操作浏览器、滚动条、窗口的宽高、事件、注册/移除事件、事件冒泡捕获、键盘、鼠标的事件、正则。

单线程 和 多线程

  • 单线程 => 同一时间只能运行一个程序

问:JS的引擎是单线程,为什么可以多个程序一起运行?
答:通过轮转时间片算法模拟多线程
步骤:

  1. 任务1、任务2
  2. 切分任务1、任务2
  3. 随机排列这些任务片段,组成队列
  4. 按照这个队列顺序将任务片送进JS进程
  5. JS线程执行一个又一个的片段

轮转时间片:短时间内轮流执行多个任务片段

  • 多线程 => 可以同时运行多个程序

引用JS脚本的两种方式

  1. 引用外部文件,填相对路径(更推荐引用外部文件的方式
<script type="text/javascript" src="js/index.js"></script>
  1. 引用内部文件
<script type="text/javascript">document.write("Inner Script")</script>

如果通过引入外部JS文件的方式的话,内部的JS就不会执行了

<script type="text/javascript" src="index.js">
  document.write('111'); // 不执行
</script>

但有时会故意写错,将其作为模板

<!-- 这里作为模板,不会执行 -->
<script type="text/html" id="name">
  <div>{{name}}</div>
</script>
<script type="text/javascript">
  // 在这里对模板中的数据进行处理
  var nameDiv = document.querySelector('#name').innerHTML;
</script>

JS与HTML、CSS的区别

HTML、CSS是标记语言,没有逻辑。

JavaScript是编程语言,具有变量、数据结构、函数、运算能力等编程语言的四个要素。

变量

变量是存储数据的一个容器,方便后续使用。

变量声明

  1. 变量声明: variable
var a;  // 变量声明:向系统申请一个存储空间,这个存储空间命名为a
a = 3;  // 变量赋值
var a = 3;  // 变量声明并赋值 => 两部分组成:变量声明 和 变量赋值
  1. 单一声明:一个var声明多个变量
var a = 1,
    b = 2;  // 变量之间用逗号分隔,分号结尾
  1. 优先级
var x = 3,
    y = 4;
var z = x + y;  // 先运算再赋值

优先级:运算 > 赋值

命名规范

  1. 不能以数字开头,能以 字母下划线$符 开头
  2. 除了开头变量可以包含 字母下划线数字$符
  3. 不能使用 关键字保留字
  4. 要有意义、语义化、结构化
  5. 变量命名小驼峰,构造函数大驼峰
  6. 用英文或看得懂的英文缩写,如:ecma

JS的值

强类型语言、弱类型语言

动态语言 => 脚本语言 => 解释型语言 => 弱类型语言(根据值判断数据类型)

静态语言 => 编译型语言 => 强类型语言(需要声明数据类型)

原始值、引用值

原始值也称为基本数据类型。

JS的原始值有5种

  • Number
    • 在JS中整型和浮点型都统称为数值型
  • String
    • 单引号和双引号之间的字符称为字符串
  • Boolean
    • 布尔值,truefalse
  • undefined
    • 未被定义的
  • null
    • 空值 => 初始化组件|函数销毁函数占位

JS的引用值

  • Object
  • Array
  • Function
  • Date
  • RegExp

栈和堆

原始值存储

原始值都存在栈内存中,先进后出,数据是永久保存的,不可修改的。 image.png

var a = 3;
var b = a;
a = 1;
document.write(b)  // 3

a 赋值给 b 时,是拷贝了一份 a 的值给 b

a 重新赋值的时候,新开辟了一个空间 a,赋值为1,原有的 a = 3,则释放 a 命名空间,但值仍留在内存中

引用值存储

引用值存在堆内存中,它的指针存栈内存。

image.png

var arr1 = [1, 2, 3, 4];
var arr2 = arr1;
arr1.push(5);
document.write(arr1, arr2)  // 1,2,3,4,5   1,2,3,4,5

arr1 赋值给 arr2 的时候,实际上是arr2指向的是arr1指向的堆的地址的,所以只要arr1改变,arr2值也改变。

image.png

var arr1 = [1, 2, 3, 4];
var arr2 = arr1;
arr1.push(5);
arr1 = [1, 2];   //数组重新赋值就和原来的数组没有关系了
document.write(arr1)  // 1,2

重新赋值的时候,是新开辟了一个栈内存空间,指向新的堆内存地址,对应新的。