欢迎光临散文网 会员登陆 & 注册

使用 JavaScript 作为编程语言

2023-06-22 16:54 作者:2015圣诞节HD  | 我要投稿

前世今生

    JavaScript 在 1995年 由Netscape公司的 Brendan Eich,在网景导航者浏览器上首次设计实现而成。1996 年  11 月,网景公司将 JavaScript 提交给 Ecma 国际进行标准化。            JavaScript的标准是 ECMAScript(European  Computer Manufacturers Association  欧洲计算机制造协会)。截至2012年,所有浏览器都完整的支持 ECMAScript 5.1,旧版本的浏览器至少支持 ECMAScript  3 标准。2015年6月17日,ECMA国际组织发布了ECMAScript的第六版,该版本正式名称为ECMAScript  2015,但通常被称为ECMAScript 6或者ES2015。

    JavaScript  是一门动态语言,动态语言是在 运行时 确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型,即变量的类型是由其应用上下文确定的。  对应的静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。

    我们知道程序运行的本质,就是CPU不断识别并计算出一组指令集(机器码)结果。使用编译器(如Java),可以事前将特定编程语言编码成中间代码,在编码为机器码,再计算结果。使用解释器(如  JavaScript),则是在程序运行时逐段读取代码,并直接生成机器码计算结果。常见的 JavaScript 解释器:

  1. 由 Google 开发的开源 JavaScript V8 引擎 on Google Chrome;

  2. 由 Mozilla 开发的开源 JavaScript Spider Monkey 引擎 on 在 Mozilla Firefox;

  3. 由 Apple 开发的 JavaScriptCore 引擎 on Safari;

    2012年 10月微软开发的自由和开源的编程语言 TypeScript 宣发。TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。一般编译器的工作步骤:

1. 词法分析:将文本字符流组织成有意义的词素序列,并转化为词法单元(key,value)序列;并记录到符号表中(符号表记录了每一个变量的名字,及其值、类型、作用域等)

2. 语法分析:使用一棵🌲语法树来重新组织词法单元序列,树能够很好地表示这个序列的执行优先级;

3. 语义分析:重新检查符号表和🌲语法树是否和约定的编程语言语法一致(比如数组的下标一定要是整数),它同时也收集类型信息存放到符号表中;

4. 中间代码生成:完成语义分析后,应当能轻易生成一种类机器的中间代码,并且易于翻译成目标代码(机器码);

5. 代码优化:编译器将会改进中间代码

6. 目标代码生成;


声明变量,并使用字面量进行赋值

👋使用 let、const、var 声明变量

通过🌻 let 和 const 声明的变量和常量具有块作用域。这意味着它们只在 let 和 const 语句所在的代码块中有定义(如函数、if/while/for 语句等);

并且在声明前使用 let const 的变量将会报错,原因是此时的变量正在暂存性死区,它们并不能像 var 变量一样优先在顶部进行声明,变量提升;

使用🌻 var  声明的变量仅仅在函数中具有作用域,如果在函数体外部使用 var ,则会声明全局变量。

👋可以赋值的七种字面量类型

(六种)基础类型:Number、String、Boolean、Symbol、undefined、null;

(一种)复杂类型:Object;

Js中的数字采用64位来存储(1bit  符号位、11bit 指数位、52bit 有效数位)即整数最值范围是 [-2~53 - 1,2~53 - 1];IEEE  754规定,有效数字第一位默认总是1,不保存在64位浮点数之中;由于小数在转换成二进制时在数学上是无限位的,实际中会被截断从而导致了小数精度丢失;

👋转换字面量的类型

可以使用 Number、String、Boolean 转换函数将某个字面量显式转化为对应类型;

也可以使用 +、-、!这些运算符进行隐式转换;

将对象转换成🌻基础类型:使用 valueOf 函数看看能否返回基础类型,如果还是得到对象(一般是它本身),将会再使用 toString 函数;

转换成数字:对于空字符串、boolean false、null 都将会转换成 number 0,而非数字的字符串、undefined 都将会转换成 number NaN;

转换成字符串:都会转变为对应字面量的字符串,如 '123'、'false' 等;

转换成布尔:对于空字符串、Number 0 NaN、undefined、null 都将会转换成 false;

👋对字面量进行运算

将运算内容均转换为基础数字类型(字符串将会转换成字符串、NaN运算结果始终为NaN)进行算数,并返回结果;



声明一个对象

    对象是一组属性的无序集合;键只能是 String 简单数据类型;可以使用字面量 {}、Object.create 方法、new 关键字 + 函数对象 来创建对象;

👋使用原型对象来实现继承

任意对象实例上都存在 __proto__ 其构造函数的唯一原型对象 { constructor: 此对象 }

任意函数对象上都存在 prototype 变量,指向其唯一原型对象

构造函数,其实例,其唯一原型对象,通过 proto 构成了三角关系;

  1. 原型对象和普通对象一样,都是 Object 的实例,它们都指向 Object 的原型对象,并且这个原型对象的 __proto__ 指向 null;这种原型对象形成的链表,就是所谓的原型链;我们可以修改任意构造函数原型对象的指向,来实现继承;

  2. 任意构造函数也是一种特殊的对象「arguments, length, name」,包括 Object 都是 Function 的实例。它们都指向 Function 的原型对象。Function 函数本身作为一个实例,它的 proto 还是它自己的原型对象;

👋关键字 new 的工作过程

👋ES6 中的 Map 对象

键可以是其他数据类型,可以进行迭代、获取长度、展开等,值键对具有顺序性

👋ES6 中的 WeakMap 对象

键只能是对象的引用,当其他地方都不再使用这些引用后会释放内存,特别适合临时计算

👋ES6 中的迭代对象

需要实现 Symbol.Iterable 方法(接口隔离原则)

👋ES6 中的 Proxy 对象

const proxy = new Proxy(target, handlers: { ...get/set })
1. 我们执行代理对象的方法达到操纵对象,而不是直接调用原对象的方法;
2. 代理将会监听整个对象,而不像 Object.defineProperty 需要循环对象属性;

👋闭包

我们讨论一个函数对象,我们就是在讨论它的🌻函数代码,以及围绕函数上下文的🌻所有其他引用;这种函数对象与作用域(即一组变量绑定)组合起来解析函数变量的机制,在计算机科学文献中被称作闭包;

👋通过组合而不是继承来设计对象

我们可以使用 Function.apply(target, array) 来使得 Function() 变为 target.Function(),其中的 this 指向 target;通过 apply 我们可以组合任意个工具类对外暴露成一个通用工具类

👋箭头函数

没有 this argument super 关键词,不能使用 new 调用、没有原型;

👋函数中的 this

指向 global;但是当使用 . 符号运行对象中的函数时,则是指向这个对象;



模块化方案

👋在 html 中划分 js 文件

在 html 中使用 <script /> 作为模块划分基础;这样做会导致文件中的声明将对同一 html 中的所有脚本可见;

也可以在 html 中使用 <script type='module'/> 作为模块划分基础;这样做会导致文件中的声明变为私有性质;

👋在 js 中 划分其他 js 文件

可以在浏览器中采用 Async Module Definition 方案;

1. 第三方库 RequireJs 中的 define/require 配合回调函掉函数异步加载Js代码;

在 Node 环境中采用 CommonJs 2009方案;即在运行时动态同步加载模块内容;

1. 每一个文件就是一个模块,拥有自己独立的作用域,变量,以及方法等,对其他的模块都不可见;

2. 每个文件中使用 module 对象变量代表当前模块,它的 exports 属性是对外的接口;暴露了内容的浅拷贝;

以ES6 import、export 关键字划分模块,在编译时加载模块内容

  1. 当进行 export default 时,它和commonjs一样暴露内容的浅拷贝;

  2. 当进行 import { } from 时,它到处内容的引用,将会影响源文件内容;



使用 JavaScript 作为编程语言的评论 (共 条)

分享到微博请遵守国家法律