现代JavaScript教程简述
该教程是属于实时更新的,对js基础知识到js函数进阶在到模块化开发都有一定的讲解.把js扒开进行底层讲解,这是我读的第二本书,其实也不能算是书把,算是文档,写笔记的初衷就是希望自己能够在软件开发这条道路上越走越远.让自己在进行知识梳理和复盘的时候,回头看笔记能够快速的进行知识灌入.
第一章:JavaScript简述
JavaScript最初被创建的目的是“使网页更生动”,这种可以被称为脚本,可以写在html文件中,在加载的时候被运行.脚本被以纯文本的形式提供或执行,他不需要特殊的准备或编译即可执行.很多人都以为JavaScript和java是大同小异的,其实则不然.
JavaScript和java的区别?
JavaScript是什么?
JavaScript一种直译式脚本语言,JavaScript基于原型的语言,属于动态类型、弱类型、内置支持类型的。它的解释器被称为JavaScript引擎,是浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML网页上使用,在网页上添加动态功能,给用户提供流畅和美观的浏览效果,通常JavaScript脚本是通过嵌入在HTML网页中实现自身的功能的。 (实现各种特效等,web前端开发基本都采用JavaScript进行开发)Java是什么?Java是一门面向对象编程语言也是静态面向对象编程语言的代表,极好地实现了面向对象理论,java吸收了C++语言的各种优点,如:简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。弃掉了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征,可以使用优雅的思维方式进行复杂的编程,Java可以进行GUI程序(桌面应用程序)和分布式系统以及嵌入式系统应用程序等程序的编写。(因为java组件易复用,高度可扩展性,多线程,还可跨平台使用的操作,所以java多用于后端)JavaScript和java的区别
- Java是面向对象的语言,JavaScript是脚本语言。
- java主要在服务端运行,javascript主要运行在客户端浏览器中。
- JavaScript是动态类型语言,而Java是静态类型语言。java在定义了一个数组的长度以后就不能再改变了,但是javascript却可以。
- JavaScript是弱类型的,即在使用前不需要声明,而是浏览器解释器在运行时检查数据类型.Java属于强类型,即所有变量在编译前必须作声明;
- JavaScript 的面向对象是基于原型的(prototype-based)实现的,Java 是基于类(class-based)的;
- Java的语法规则比JavaScript要严格的多,功能要强大的多。
- java语言的代码是一种HTML没有关系的语言;javascript语言的代码是一种文本字符格式,可以直接嵌入HTML文档中,并且可动态加载。
- 并且它们的执行方式也是不一样的,Java是介于解释型和编译型语言之间的一种语言,java的源代码在传递到客户端执行之前,必须经过编译,通过相应平台上的解释器,实现独立于某个特定的平台编译代码的束缚。JavaScript是一种解释性编程语言,其源代码在发往客户执行之前不需经过编译,而是将文本格式的字符代码发送给客户编由浏览器解释执行。
- 再其次两者的用途也不一样,java广泛应用于个人PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网等,而Javascript的用途是:1.嵌入动态文本于HTML页面;2.对浏览器事件做出响应; 3.读写HTML元素;4.在数据被提交到服务器之前验证数据;5.检测访客的浏览器信息; 6.控制cookies,包括创建和修改等。
什么是JavaScript?
JavaScript由三部分组成:1.核心(ECMAScript)2.文档对象模型(DOM)3.浏览器对象模型(BOM)
- ECMAscript是JavaScript的国际语言规范标准,准确来说就是描述了JS的语法和基本对象;
- BOM是浏览器对象,各个浏览器厂商根据DOM在各自浏览器上的实现,每个浏览器略有不同,BOM主要是操作浏览器出现的API,window 是其的一个对象;
- DOM是文档对象,DOM把整个页面规划成由节点层级构成的文档,也是W3C制定的标准.(所有浏览器必须遵守的公共标准).
JavaScript引擎是什么?
JavaScript可以在浏览器中运行,服务器中运行,也可以在任意搭载了JavaScript的引擎中设备中运行,有些人也把JavaScript引擎称为'JavaScript虚拟机';不同的JavaScript引擎有着不同的名字
- V8引擎是Chrome(谷歌浏览器,web前端开发最常用的就是谷歌)和Opera(欧朋浏览器)中的JavaScript引擎;
- SpiderMonkey引擎是Firefox(火狐浏览器,web前端其次选择的)中的JavaScript 引擎。
- Chakra引擎是IE(IE浏览器前端开发最为忌讳的一款浏览器)所用的;
- ChakraCore引擎是 Microsoft Edge(微软浏览器,桌面运维工作浏览器的首选,因为谷歌受到国内安全网络限制)所用的;
- Nitro引擎和SquirrelFish引擎是Safari(苹果浏览器);
为什么前端开发采用的都是V8引擎呢?
- 在计算器行业里引擎就是一种软件的转换器,将的代码输入后产出符合机器识别和操作的命令。当JavaScript执行后,引擎负责解析js代码,编译成不同环境的机器语言。由于javascript语言是动态解释性语言,因此js引擎的性能压力就会非常大,这是相较于java,c++等编译型语言来说。所以性能将是衡量现代js引擎的核心指标之一。
- V8引擎是谷歌特别为了Chrome浏览器可以高速运行网页应用而开发的。谷歌浏览器利用AWebKit作为渲染引擎。 WebKit的标准配备有称为JavaScriptCore的JavaScript引擎,但Chrome则以V8取代之,因为V8引擎相对于JavaScriptCore性能会更好;V8引擎的执行和JavaScriptCore的执行
- 第一步他们都会用解析器解析,生成抽象语法树,然后使用JIT(Just In Time)的全代码生成器生成本地的代码。这里的全代码生成器(full-code generator)属于JIT编译器的一部分,区别于JavaScriptCore的字节码中间结果,这样的设计主要是性能的考虑,但同样在某些场景下会触发更多耗时的计算。
- V8引擎对数据分片管理和垃圾回收采用的方案是,数据层面使用Zone类,这是引擎调度的最小单元,整块的存取删除Zone区域,在Zone内部保存同类型的数据类型。如果要回收也是回收整个Zone内存块,这样做的好处是可以高效的处理一大批类似的操作,比如生成抽象语法树,但缺点也是非常明显,在Zone内的零散数据结构很难被及时清理导致内存消耗上升。
- javascriptCore则不然,javaScriptCore引入了很多的苹果公司的技术,例如LLVM、DFG(Data-Flow Graph)JIT编译器。与V8引擎最大的不同在于其在生成抽象语法树后并不直接生成本地代码,而是生成跨平台的字节码,然后借助类似于Java虚拟机的解释器来解析字节码,在内存管理这块,JavaScriptCore和V8是类似的,分代策略及Zone的变体JSGlobalData;
总结:引擎的转化十分复杂,但是原理却十分简单:引擎读取javascript脚本文件,然后将脚本文件转化为机器语言,机器代码在执行。同时引擎会对流程中的每个阶段都进行优化。它甚至可以在编译的脚本运行时监视它,分析流经该脚本的数据,并根据获得的信息进一步优化机器代码。
浏览器内核是什么?
所有的了浏览器内核就是浏览器最为核心的东西,也被称为‘渲染引擎’和‘排版引擎’以及‘解释引擎’;
- 现在市面上的浏览器内核可以分为五种:
- trident内核是IE浏览器的内核,国内双核浏览器的内核之一,此内核只能用于Windows平台且不是开源的,Trident内核一直延续到IE11,IE11的后继者Edge采用了新内核EdgeHTML;
- Blink内核,是谷歌浏览器和欧朋浏览器共同研发的,基于webKit2(2010年苹果发布)中WebCore组件的一个分支进行开发的,Blink比上一代的引擎(Chromium内核)更为优秀,不仅精简了代码还改善了DOM框架同时安全性也获得了提升(谷歌现在采用的就是Blink内核);
- Gecko内核是开源内核,之后被FireFox(火狐浏览器)采用,最大优势是跨平台,主要Microsoft Windows、Linux、MacOs X等主要操作系统中使用;
- Webkit内核是开源内核,Webkeit内核的鼻祖是Safari(苹果浏览器),以前的Chrome(谷歌浏览器)采用的是Webkeit内核,WebKit内核主要是由两个引擎构成的,一个是渲染引擎“WebCore”,一个是javascript解释引擎“JSCore”,它们均是从KDE的渲染引擎KHTML及javascript解释引擎KJS衍生而来;
- Chromium内核是一款开源内核,是WebKit的一个分支,虽然属于webKit的分支但是把代码可读性和和编译速度提高很多,之前需要一天编译的代码,现在两个小时搞定,谷歌还专门研发了自己的JS引擎V8,对JavaScript的运算速度有着很大的提高;
JavaScript注意点
JavaScript不提供底层的访问,如cpu和内存等,JavaScript的能力取决于运行环境,为了用户的安全,JavaScript的能力是受一定限制的,是为了防止恶意网页获取用户私人信息或损害用户数据。有以下几条:
- 网页中的 JavaScript 不能读、写、复制和执行硬盘上的任意文件。它没有直接访问操作系统的功能。
- 现代浏览器允许 JavaScript 做一些文件相关的操作,但是这个操作是受到限制的。仅当用户做出特定的行为,JavaScript 才能操作这个文件。
- 有很多与相机/麦克风和其它设备进行交互的方式,但是这些都需要获得用户的明确许可。
- 浏览器对于不是同域名、协议或者端口任一不相同的网站做出不能互相进行访问的操作,它们都不能相互通信。这就是所谓的“同源策略”。如果在浏览器外做这些事情,则不受限制,JavaScript与HTML/CSS 完全集成且被所有的主流浏览器支持,并且默认开启,JavaScript也可以用来创建服务器和移动应用等操作。
- 在浏览器中F12打开开发者控制台,然后再console里面通过shift+enter可以进行换行,enter是执行代码.
代码编译器
代码编译器分为俩种集成环境编译器和轻量编译器。
- 集成环境编译器是IDE(集成开发环境)是用于管理整个项目的,如Visual Studio Code,WebStorm免费;
- 轻量编辑器没有IDE功能那么强大,但是它们一般很快、优雅而且简单主要用于快速打开和编辑文件。也会有各种各样的插件.
第二章 JavaScript基础知识
- JavaScript可以通过script标签插入到 HTML 文档的任何地方。(一般插入在body标签里面最底部);
- script标签中的JavaScript代码,当浏览器遇到script标签时代码会自动运行。
Script标签特性
//一般很少用到这些特性type 和 language 特性不是必需的。 //type特性 //HTML4中有一些特性要求有type="text/javascript",但是这种使用在JavaScript模块上。 //language特性 //这个特性是为了显示脚本使用的语言。现在已经没有任何意义,因为语言默认就是 JavaScript。 //脚本前后的注释=>这是特别老的代码,用于不支持script标签的古老的浏览器隐藏JavaScript代码的; <script type="text/javascript"><!-- ... //--></script> //如果设置了src特性,script 标签内容将会被忽略。一个单独的 <script> 标签不能同时有 src 特性和内部包裹的代码。 //外部引入 <script src="/js/script2.js"></script> //内部使用 <script> alert('hello') </script>
最简单的脚本才嵌入到 HTML 中,复杂的脚本存放在单独的文件中,这样使用独立文件可以让那个浏览器进行下载缓存到本地,提高页面渲染速递。
代码结构
//一般单句代码能独占一行的就独占一行,但是不得超过120个字符,过多的代码只会不利于阅读. alert('Hello'); alert('World'); //每句代码后面建议跟上分号做一个结尾,换行也是一'隐式分号',这是JavaScript自动插入分号的操作,只是我们看不见而已; alert(1 +1 +1); //但是有的时候'隐式分号',会出现一些错误,这俩行代码,单独拿出去都能运行,但是如果放到一块且 //第一句不加分号的情况下则会报错; alert("There will be an error") [1, 2].forEach(alert) //其实引擎是把他们俩句代码解析成一句代码了,由于JavaScript不会自动在[]前面添加'隐式分号'所以报错; alert("There will be an error")[1, 2].forEach(alert)
注释
//JavaScript注释分为俩种,单行注释和块级注释,都可以跟在代码后面写,不过一般跟代码的都采用单行注释 //注释并不会被引擎解析或执行,引擎会直接忽略掉注释的部分,所以注释里面放代码,代码则不会得到执行 //注释是用于解释你当前的这块代码做什么用的为什么这么做,以便于过段时间后自己还能知道当前的代码是做什么的 //单行注释 windows的电脑快捷键是shift+/ /* 块级注释也叫作多行注释 windows的电脑快捷键是Ctrl+Shift+/ */ //mac电脑则是 把ctrl改成cmd shift改成Option //注释不支持嵌套注释 //注释会增加代码总量,有很多工具可以帮你把代码部署到服务器之前缩减代码。 //这些工具会移除注释,这样注释就不会出现在发布的脚本中。所以,注释对我们的生产没有任何负面影响。
严格模式
'use strict',把这串字符放到js文件的最顶部,将对当前的js文件开启严格模式,之前的JavaScript在创建初期因为不完善的决定留下了很多问题,比如null的类型会是object,默认是不生效的,也可以放在函数体中,放在函数体中的最顶部,整个函数体会开启严格模式;
//注意点: //1.必须得保证 'use strict'是在js文件或者函数文件最顶部,负责脚本运行时会直接忽略。 //2.一但进入严格模式则无法取消。 //3.浏览器控制台默认是不启动的,可以通过shift+eneter输入多行代码,把严格模式的声明放在最顶端。 //4.如果是旧版浏览器请采用立即执行函数里面声明严格模式,代码如下: (function() { 'use strict'; console.log('hello'); })(); //5. “classes” 和 “modules” 会默认启动严格模式。 //6.严格模式和旧版的差异并不多,所以无需过分在意。
严格模式有以下几点要求
//1.不允许使用var关键字定义全局变量 //2.不允许对变量使用 delete 操作符,抛出ReferenceError //3.不可对对象的只读属性赋值,不可对对象的不可配置属性使用 delete 操作符,不可为不可拓展的对象添加属性, //均抛 TypeError //4.对象属性名必须唯一 //5.函数中不可有重名参数 //6.在函数内部对修改参数不会反映到 arguments 中 //7.淘汰 arguments.callee 和 arguments.caller //8.不可在 if 内部声明函数 //9.抛弃 with 语句 //10.不允许使用八进制字面量
变量
变量的作用就是用来存储信息的,变量是数据的'命名储存';
//定义变量 //var 定义全局变量,在全局那个地方都可以访问到,但是var具有变量提升,同时也因为变量提升引起了全局变量污染的问题,当var被 //第一次声明的时候,第二次声明会覆盖掉第一次声明的var,这就叫做变量污染. //let 定义块级作用域的变量,是具有块级作用域的,当let在俩个函数内声明同一个变量,因为会块级作用域的原因,这是俩个变量, //不会存在变量污染的问题,let声明的变量实际上也会有提升,只不过提升后会将其先放入到“暂时性死区”,如果访问的变量位于暂时性 //死区则会报错,只有当代码运行到该变量的声明语句时,会将其从暂时性死区中移除,所以尽量不要再let声明前调用let. //const 必须赋值且不可更改值的变量,他也是具有块级作用域的,且不支持声明前置.
声明变量
一个等号=是赋值,二个==是比较值是否相同,===三个等号是比较值于类型是不是都是相同的; //声明或定义变量 let a; var a; //定义变量 一个=号等于给当前的变量进行赋值操作. //给变量赋值的的值会存储在变量的内存区域中 let b=1; var b=2; //常量赋值的值不可被更改,修改就会报错(一般是在确定不会在修改这个值的情况下才使用); //普遍的做法是将常量用作别名,以便记住那些在执行之前就已知的难以记住的值; //使用大写字母和下划线来命名这些常量,大写命名的常量仅用作“硬编码(hard-coded)”值的别名; //硬编码===值在执行之前或在被写入代码的时候,我们就知道值是什么了; const A=3; //声明多个变量可以使用逗号进行分割 let a=1,b=2,c=4; 变量在同一作用域下被声明两次会报错,因此变量只能在同一作用域下被声明一次 // SyntaxError: 'a' has already been declared
访问变量
let b=2; //访问(赋值过后的变量可以通过变量名直接来访问) console.log(b);
更改变量的值
let a=1; //改变变量的值(当值发生改变的时候,之前的数据就会从变量中删除) a=100; //还可以把变量的数据拷贝进另一个变量中 let b=a;
扩展:函数式语言,变量一旦被赋值,则一直存在,如果重新赋值,则会重新强制性声明一个变量并赋值,无法重用之前的变量,比如 Scala 或 Erlang语言,主要是用于并行计算;变量命名
- 变量名称必须仅包含字母或数字或符号或$或 _,首字符必须非数字。
- 如果命名过长则可以采用大驼峰或者小驼峰命名法,首字符大写或首字符小写;
- 美元符号 '$' 和下划线 '_' 也可以用于变量命名。它们是正常的符号,就跟字母一样,没有任何特殊的含义。
- 变量是区分大小写的,大写的A和小写的a是俩个不同的变量;
- 允许非英文字符作为变量名,但不推荐,因为国际惯例就是使用英文进行变量命名;
- 保留字不能作为变量命名,因为它们被用于编程语言本身,如果使用将会报错;严格模式下的赋值
// 不在脚本中使用 use strict 声明启用严格模式,变量则不用声明即可赋值,这是为了保持对旧脚本的兼容; num = 5; // 如果变量 "num" 不存在,就会被创建 alert(num); // **5**
"use strict"; //开启严格模式后则会报错 num = 5;
变量命名规范及意义
- 在一个实际项目中,大多数的时间都被用来修改和扩展现有的代码库,而不是从头开始写一些完全独立的代码。当一段时间后,我们做完其他事情,重新回到我们的代码,找到命名良好的信息要容易得多;
- 变量名应该有一个清晰、明显的含义,对其存储的数据进行描述。
- 使用易读的命名,比如 userName 或者 shoppingCart。
- 诸如 a、b、c 这种缩写和短名称远一点,除非你真的知道你在干什么
- 变量名在能够准确描述变量的同时要足够简洁。不好的例子就是 data 和 value,这样的名称等于什么都没说。如果能够非常明显地从上下文知道数据和值所表达的含义,这样使用它们也是可以的。
- 脑海中的术语要和团队保持一致。如果网站的访客称为“用户”,则我们采用相关的变量命名,比如 currentUser 或者 newUser,而不要使用 currentVisitor 或者一个 newManInTown。
- 不建议倾向于重用现有的变量,而不是声明一个新的变量。
- 现在 JavaScript 压缩器和浏览器都能够很好地对代码进行优化,所以不会产生性能问题。为不同的值使用不同的变量可以帮助引擎对代码进行优化。