JavaScript简介
前端三元素
- HTML:通过各种元素搭建页面结构
- CSS:负责页面样式:形状、大小、颜色、动画等
- JavaScript:控制页面行为:部分动画效果、页面与用户的交互、页面功能
JavaScript的概念
JavaScript(通常缩写为JS)是一种高级的、解释型的编程语言。JavaScript是一门基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。它提供语法来操控文本、数组、日期以及正则表达式等,不支持I/O,比如网络、存储和图形等,但这些都可以由它的宿主环境提供支持。它已经由ECMA(欧洲电脑制造商协会)通过ECMAScript实现语言的标准化。它被世界上的绝大多数网站所使用,也被世界主流浏览器(Chrome、IE、Firefox、Safari、Opera)支持。
虽然JavaScript与Java这门语言不管是在名字上,或是在语法上都有很多相似性,但这两门编程语言从设计之初就有很大的不同,JavaScript的语言设计主要受到了Self(一种基于原型的编程语言)和Scheme(一门函数式编程语言)的影响。在语法结构上它又与C语言有很多相似(例如if条件语句、switch语句、while循环、do-while循环等)。
在客户端,JavaScript在传统意义上被实现为一种解释语言,但在最近,它已经可以被即时编译(JIT)执行。随着最新的HTML5和CSS3语言标准的推行它还可用于游戏、桌面和移动应用程序的开发和在服务器端网络环境运行,如Node.js。
JavaScript的运行原理
此小节内容转自文章:https://www.cnblogs.com/amy2011/archive/2013/06/11/3131565.html
宿主环境
JS的运行环境一般由宿主环境和执行期环境共同构成,宿主环境是由外壳程序(如web浏览器就是一个外壳程序)生成,执行期环境是由嵌入到外壳程序中的JS引擎(/JS解释器)生成的,在执行期环境JS可以生成内置静态对象、初始化执行环境等。
- 宿主环境一般由外壳程序创建和维护,在一个宿主环境中可以运行多种脚本语言(如JavaScript),以虚拟机的方式提供一个跨语言跨平台的宿主环境。
- 宿主环境一般会创建一套公共对象系统,该系统对所有脚本都开放,允许它们自由访问,还提供了公共接口,用来装载不同的脚本语言引擎。
- 脚本语言本身并不提供IO,也没有与系统和外界通信的能力,更不存在管理内存,修改注册表等行为,这些行为全部由宿主环境完成
- 外壳程序不仅是web浏览器,任何可以提供JS引擎执行环境的都可以称之为外壳程序,外壳程序还可以利用符合标准的扩展接口接纳更多的插件、组件或ActiveX控件等DLL应用
- 执行期环境是由宿主环境通过脚本引擎创建的一个代码解析初始化环境。
Js的解析过程
1.编译:
预处理,在这一过程中,JS解释器完成对JS代码的预处理,即将JS脚本代码转换成字节码。
2.运行:
在这一阶段,将编译结束时生成的字节码转换成机械码,按顺序执行。
JS是一种解释型语言,所谓解释型是指代码在执行时被解释器一行一行动态编译和执行,而不是执行前完成编译,即边编译边执行,一般的编译性语言的编译过程是由编译器完成,进行词法分析、语法分析、语义检查、代码优化、最后生成字节码,JS的是词法分析、语法分析,建立语法树,开始解释执行。
3.执行期:
JS引擎按着作用域机制来执行,JS的变量和函数作用域是在定义时决定的,而不是执行时才决定的,所以JS解释器只需要通过静态分析就能确定每个变量和函数的作用域,这种作用域称为静态作用域,当JS解释器执行函数时,先创建一个执行环境,在这个执行环境中创建一个调用对象,在这个对象内存储当前域中所有的局部变量、参数、嵌套函数、外部引用和父级引用列表等,通过声明语句定义的变量和函数在预编译阶段就已经存储到符号表中了,然后把它们与调用对象中的同名属性进行映射即可。调用对象的生命周期和函数的生命周期一致,JS解释器通过作用域链将多个嵌套的作用域连在一起,并利用该链条来检索变量的值。
ES6开启JavaScript的新时代
- ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
- ECMAScript 和 JavaScript 的关系是,前者是后者的标准,后者是前者的一种实现(另外的ECMAScript 方言还有 Jscript 和 ActionScript)。
- ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了ES2015、ES2016、ES2017 等等.
DOM的学习
DOM介绍
- DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model),它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。
- 浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree),所有的节点和最终的树状结构,都有规范的对外接口。
- DOM 只是一个接口规范,可以用各种语言实现。所以严格地说,DOM 不是 JavaScript 语法的一部分,但是 DOM 操作是 JavaScript 最常见的任务,离开了 DOM,JavaScript 就无法控制网页。另一方面,JavaScript 也是最常用于 DOM 操作的语言。后面介绍的就是 JavaScript 对 DOM 标准的实现和用法。
学习DOM
本文会介绍常用的DOM类型,想了解更多的朋友可以参考链接:https://wangdoc.com/javascript/dom/index.html
Docunent节点
document.links //返回当前文档所有设置href的<a>和<area>节点
document.location //返回当前网页位置,协议以及主机名
document.URL //返回当前网页位置
document.tittle //返回当前文档的标题,默认情况下,返回<title>节点的值,但是该属性是可写的,一旦被修改,就返回修改后的值
document.cookie //显示当前角色的cookie信息
document.querySelector() //接受一个 CSS 选择器作为参数,返回匹配该选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点;如果没有发现匹配的节点,则返回null
document.getElementsByTagName() //搜索 HTML 标签名,返回符合条件的元素。它的返回值是一个类似数组对象(HTMLCollection实例),可以实时反映 HTML 文档的变化。如果没有任何匹配的元素,就返回一个空集
document.getElementsByClassName() //返回一个类似数组的对象(HTMLCollection实例),包括了所有class名字符合指定条件的元素,元素的变化实时反映在返回结果中。
Node接口
var div = document.getElementById('d1');
div.nodeName //找到'd1'节点,并且返回d1的节点名称
div.textContent //返回当前节点和它的所有后代节点的文本内容
div.nextSibling //返回紧跟在当前节点后面的第一个同级节点;如果当前节点后面没有同级节点,则返回null
div.parentNode //返回当前节点的父节点
div.childNodes //返回一个类似数组的对象(NodeList集合),成员包括当前节点的所有子节点
Element节点
- Element.attributes属性返回一个类似数组的对象,成员是当前元素节点的所有属性节点;
- Element.className属性返回一个类似数组的对象,当前元素节点的每个class就是这个对象的一个成员。
- Element.innerHTML属性返回一个字符串,等同于该元素包含的所有 HTML 代码。该属性可读写,常用来设置某个节点的内容。它能改写所有元素节点的内容,包括和元素。
属性的操作
HTML 元素包括标签名和若干个键值对,这个键值对就称为“属性”(attribute).
- Element.getAttribute方法返回当前元素节点的指定属性。如果指定属性不存在,则返回null。
- Element.setAttribute方法用于为当前元素节点新增属性。如果同名属性已存在,则相当于编辑已存在的属性。
CSS操作
CSS 与 JavaScript 是两个有着明确分工的领域,前者负责页面的视觉效果,后者负责与用户的行为互动。但是,它们毕竟同属网页开发的前端,因此不可避免有着交叉和互相配合。
div.setAttribute(
'style',
'background-color:red;' + 'border:1px solid black;'
);
上面的Js代码等同于下面的HTML代码:
<div style="background-color:red; border:1px solid black;" />
window.getComputedStyle方法,用来返回浏览器计算后得到的最终规则。它接受一个节点对象作为参数,返回一个 CSSStyleDeclaration 实例,包含了指定节点的最终样式信息。所谓“最终样式信息”,指的是各种 CSS 规则叠加后的结果。
var div = document.querySelector('div');
var styleObj = window.getComputedStyle(div);
styleObj.backgroundColor
上面代码中,得到的背景色就是div元素真正的背景色;
关于DOM的学习就到这里,想了解更多的朋友可以访问上面的网页:https://wangdoc.com/javascript/dom/index.html
Js的数据类型
Number
JavaScript 对整数提供四种进制的表示方法:十进制、十六进制、八进制、二进制。
- 十进制:没有前导偶的数值。
- 八进制:有前缀0O或00的数值,或者有前导0、且只用到0-7的八哥阿拉伯数字的数值。
- 十六进制:有前缀0x或0X的数值。
- 二进制:有前缀0b或0B的数值。
Boolean
- 布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示,布尔值只有这两个值。
- 下列运算符会返回布尔值:
前置逻辑运算符: ! (Not)
相等运算符:===,!==,==,!=
比较运算符:>,>=,<,<=
- 除了下面六个值被转为false,其他值都视为true:
undefined
null
false
0
NaN(非数字)
""或''(空字符串)
- Boolean 对象在 JavaScript 中的用处不大,因为它经常会造成人们的误解
String
String字符串的举例
举例:
var name = 'catt1e'; //定义name
var age = 11; //age
var hello = `我是${name}, 我今年${age}`; //字符串的拼接,用到反引号
String字符串的常用方法
- String.charAt( ) 返回字符串中的第n个字符
- String.charCodeAt( ) 返回字符串中的第n个字符的代码
- String.concat( ) 连接字符串
- String.fromCharCode( ) 从字符编码创建—个字符串
- String.indexOf( ) 检索字符串
- String.lastIndexOf( ) 从后向前检索一个字符串
- String.localeCompare( ) 用本地特定的顺序来比较两个字符串
- String.match( ) 找到一个或多个正则表达式的匹配
- String.replace( ) 替换一个与正则表达式匹配的子串
- String.search( ) 检索与正则表达式相匹配的子串
- String.slice( ) 抽取一个子串
- String.split( ) 将字符串分割成字符串数组
- String.substr( ) 抽取一个子串
- String.substring( ) 返回字符串的一个子串
- String.toLocaleLowerCase( ) 把字符串转换小写
- String.toLocaleUpperCase( ) 将字符串转换成大写
- String.toLowerCase( ) 将字符串转换成小写
- String.toString( ) 返回字符串
- String.toUpperCase( ) 将字符串转换成大写
- String.valueOf( ) 返回字符串
- String.includes():返回布尔值,表示是否找到了参数字符串
- String.startsWith():返回布尔值,表示参数字符串是否在原字符串的头部
- String.endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部
- String.repeat() 方法返回一个新字符串,表示将原字符串重复n次
- String.padStart() 用于头部补全
- String.padEnd()用于尾部补全
Null与Undefined
区别
1.null值为空,不是一个全局的标识符
2.undefined全局标识符,表示初始值未定义
代码演示
typeof null // "Object"
typeof undefined //"undefined"
Symbol
概念
一种新的类型,得到一个唯一的值
用法
用于对象的属性名:一种是字符串;另一种是Symbol 类型,可以保证不会与其他属性名产生冲突。
Object的概念
对象(Object)的概念
- js对象是一种无序的集合数据类型,由若干个键值对组成。
- 对象是属性的容器,每个属性有名字和值,用k:v对应的关系表示,逗号隔开
- 对象是无类型的,k,v的值都可以自定义
- 对象可以嵌套,即对象包含对象,但不建议太多层
- 属性可以动态添加
- 所有的属性都是字符串,对应的值可以是任意的类型
对象(Object)的创建
var a = {};
const b = {};
a.name = 'catt1e'; //添加name属性
逻辑判断
JavaScript运算符
算数运算符
+ - * % / ++ --
赋值运算符
= += -= *= /= %=
比较运算符
==
===三等需要满足类型和内容均相同
!= 不等于
!== 值不等或类型不等
> < >= <=
逻辑运算符
&& || !
与&&
或 | |
非!
条件运算符
if ...else
(a === b) ? x : y
循环语句
do...while语句
- 一直重复,直到条件为假(false)
- 至少执行一次
while语句
- 条件为真(true)就一直执行
- 可能一次不执行
switch语句
switch (val){case a: xxx; break; ...}
for语句
- for...in;
- for...of:
- 在可迭代对象上创建了一个循环
- 注意 for...in 和for ...of 的区别
- for...in循环读取键名,for...of循环读取键值
- 数组,set,map,对象,字符串
函数
限于篇幅,本快内容主要说明函数的定相关概念及用途,相关代码未直接书写
初识函数
定义
function name ([param[, param,[..., param]]]) { [statements] }; //一般函数的定义
function (){}; //匿名函数的定义
运行
- 立即执行函数表达式
- 赋给一个变量
- 赋给对象属性
- 作为参数传递给另一个函数(高阶函数)
- 将函数作为返回值
参数
- 形式参数
- 默认参数
- 剩余(rest)参数
返回值(return)的作用
- 返回函数执行的结果
- 结束函数的运行
- 阻止默认行为
函数的解构赋值
概念
从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
几种解构赋值的操作
let [a, b, c] = [1, 2, 3]; //a=1,b=2,c=3
let [x, , y] = [1, 2, 3]; //x=1,y=3
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
let { foo,baz } = { foo: "aaa", bar: "bbb" };
const [a, b, c, d, e] = 'hello'; //分解hello分别赋值给abcde五个字母
let {length : len} = 'hello';
作用域
变量
- 全局变量:在函数之外定义的变量,函数内部可以访问
- 局部变量:在函数内部定义的变量,只能在函数内部访问,外部无法访问
全局作用域(Global Scope)
- 最外层函数和在最外层函数外面定义的变量拥有全局作用域
- 所有末定义直接赋值的变量自动声明为拥有全局作用域
- 所有 window 对象的属性拥有全局作用域
局部作用域(Local Scope)-函数作用域
- 定义了一个函数的同时,就创建了一个函数作用域
- 内部定义的变量不能在函数外部访问
- 嵌套的作用域变量从当前作用域往上寻找声明,找不到则报错
- 函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域
全局和局部作用域的关系
- 在函数体内,局部变量的优先级高于同名的全局变量
- 定义在全局域中的函数可以访问所有定义在全局域中的变量
块级作用域
1.let
- let声明的变量只在代码块有效
- let声明的变量不存在变量提升
- 不能重复声明
2.const
- 创建块级作用域
- 新建一个同名变量,不能重复赋值,但可以在新的作用域使用
3.var
使用var定义变量可能导致变量提升,不建议使用var定义函数
4.this 关键字
- 直接被调用的函数,this为全局对象
- 被某个对象调用的函数,this为当前对象
函数闭包
由于在 Javascript 语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成定义在一个函数内部的函数
闭包的用途
- 可以读取函数内部的变量(作用域链)
- 让这些变量的值始终保持在内存中
- 注意,外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所
- 以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。
正则表达式
各种语言中的正则表达式都差不多,此处不花笔墨介绍了,在此附加一个链接,需要的时候供读者查找(正则表达式)[https://www.w3school.com.cn/jsref/jsref_obj_regexp.asp]
prototype与class
概念
传统的Javascript是动态语言,又可称之为Prototype-based Language,JavaScript继承方法是使用prototype,透过指定prototype属性,便可以指定要继承的目标。属性可以在运行时添加到或从对象中删除,引擎会为运行中的对象创建一个属性字典,新的属性都要透过字典查找属性在内存中的位置。
原型链原理
当一个属性/方法引用在一个对象上发生,而这样的属性/方法又不存在时,这个链接就会被使用。在这种情况下,[Prototype]链接告诉引擎去那个被链接的对象上寻找该属性/方法。接下来,如果那个对象也不能满足查询,就沿着它的 [[Prototype]] 查询,如此继续。这种对象间的一系列链接构成了所谓的“原形链”。
原型链的应用
可以想到,如果一个属性位于原型链的顶端,那么这个查找过程将会十分低效。所以如果重复查找原型链顶端的属性,通过临时变量来缓存结果是个提高性能的不错的方法。
Js中原型链的详解
prototype 原型
我们创建的每个函数都有一个 prototype(原型)属性使用原型的好处是可以让所有对象实例共享它所包含的属性和方法换句话说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型中
- 理解原型对象
在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值 - 原型的动态性
由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能够立即从实例上反映出来,即使是先创建了实例后修改原型也照样如此,;实例中的指针仅指向原型,而不指向构造函数
proto
当调用构造函数创建一个新实例后,该实例的内部将包含一个指针 proto,指向构造函数的原型,简单来说,当我们访问一个对象的属性时,如果这个属性不存在,那么就会去 proto 里找,这个 proto 又会有自己的 proto,于是就这样一直找下去,直到找到为止
原型链
- JavaScript 中描述了原型链的概念,并将原型链作为实现继承的主要方法其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法
- 每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针
- 假如我们让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针
- 假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条
箭头函数
定义
- 箭头函数使用类似于=>这样的语法定义函数,
- 支持表达式模式和语句模式
代码示范
var sum = (x, y) => {return x+y}
['a',,'b'].filter => (x==true) // 数组的箭头函数
作用域的区别
- 箭头函数:作用域最大特点在于和父作用域具有一样的this。绑定定义时所在的作用域
- 普通函数:this 既不指向函数自身也不指向函数的词法作用域,this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。
- 箭头函数根本没有自己的this,导致内部的this就是外层代码块的this
Ajax介绍
想了解Ajax的可以参照此博客Ajax学习网站
异步操作:promise
promise介绍
- Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
- 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise提供统一的 API,各种异步操作都可以用同样的方法进行处理。
- 为异步编程提供了一种新的方式,Promise把未来将用到的值当做一等对象
- 给你一个诺言,要么成功(上天堂),要么失败(下地狱)
promise特点
- 对象的状态不受外界影响。
- Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
- 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
- 只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为resolved(已定型)。
- 如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
- 调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面
Import:Module体系的相关知识
- 模块(module)体系,将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。
- ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
- ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
- 模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
- 一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。