JavaScript [ 1995 Brendan Eich ]
推荐好的文章 [Javascript诞生记 -阮一峰]:http://www.ruanyifeng.com/blog/2011/06/birth_of_javascript.html [ TS 实现设计模式 ]:https://refactoringguru.cn/design-patterns/typescript
文章目录
- JavaScript [ 1995 Brendan Eich ]
-
- 一: 了解 JS
-
- 1. 历史和发展
- 2. 基础使用
- 二: 基础语法
-
- 1. 变量常量
-
- 1. 基础知识
- 2. var let const
- 3. 暂时性死区
- 4. 传值与传址
- 2. 严格模式
- 3. 转义字符
- 三. 数据类型
-
- 1. 类型检测
- 2. Null
- 3. Undefined
- 4. String
-
- 1. 声明字符串的方式
- 2. 转义符串
- 3. 转换数据类型
- 4. 返回值类型
- 5. 属性
- 6. String 对象的方法
-
- localeCompare()
- charCodeAt()
- charAt()
- String.fromCharCode()
- slice()
- substring()
- substr()
- concat()
- indexOf()
- lastIndexOf()
- includes()
- startsWith()
- endsWith()
- search()
- match()
- replace()
- split()
- repeat()
- padStart() padEnd()
- trim()
- trimStart(),trimEnd()
- toLowerCase() toUpperCase()
- 6. 类型转换
- 5. Number
-
- 1. 分类
- 2. NaN遇到的坑
- 3. 转换数据类型
- 4. number 函数
- 6. Boolean
-
- 1. 转换数据类型
- 2. 转换显示类型
- 7. Array
-
- 1. Array.方法
-
- Array.isArray()
- Array.from()
- Array.of()
- 2. 增删改操作
-
- pop()
- shift()
- push()
- unshitf()
- slice()
- splice()
- fill()
- copyWithin()
- 3. 拼接分离
-
- concat()
- join()
- 4. 排序
-
- sort()
- reverse()
- 5. 查找
-
- indexOf()
- lastIndexOf()
- includes()
- find()
- findindex()
- every()
- some()
- 6. 循环操作
-
- filter()
- forEach()
- map()
- reduce()
- keys()、values()、entries()
- 7. 展开语法
- 8. 解构赋值
- 8. Function
-
- 1 函数的定义/声明
- 2. 箭头函数
- 3. 函数默认值
- 9. Object
- 10. global
- 11. Math
- 12. Date
-
- 1. 创建Date对象的两种写法
- 2. 日期格式化
- 3. 时间戳
- 4. 所有时间函数
- 5. moment.js
- 13. RegExp
-
- 1. 使用正则表达式基础
- 2. 正则表达式符匹配
-
- 1 两种匹配
- 2. 字符组
- 3. 量词
- 4. 多选分支
- 3. 正则表达式位置匹配
-
- 1. ^和$
- 4. 位置的特性
- 14. set
- 15. WeakSet
- 16. symbol
-
- 1. Symbol() 定义方式一
- 2. Symbol() 定义方式二
- 3. 在对象属性中的使用
- 4. 遍历属性
- 17. Map
- 18. WeakMap
- 四: 运算符
-
- 1. 算数运算符
- 2. 赋值运算符
- 3.比较运算符
- 4. 字符串运算
- 5. 逻辑运算
- 6. 位运算
- 五: 流程控制
-
- 1. 顺序结构
- 2. 分支结构
- 3. 循环结构
- 4. 跳出判断循环
- 5. 对引用类型的循环
- 六: 函数
-
- 1. 函数的定义
- 2. 函数作用域
- 3. 回调函数
- 4. 递归函数
- 5. 内部函数
- 6. 函数表达式
- 7. arguments
- 8. 闭包
- 9. 函数参数的默认值
- 10. 函数与方法的区别
- 11. 立即执行函数
- 12. fn() 和 fn 的区别
- 七: DOM
-
- 1. 节点与元素
- 2. 节点属性
- 3. 获取节点
- 4. 操作节点
- 5. 元素节点
- 6. 文本节点
- 7. 文档节点
- 8. 操作cookie
- 八: BOM
-
- 1. window对象
- 2. window 属性方法
- 3. location子对象
- 4. history子对象
- 5. screen子对象
- 6. navigator子对象
一: 了解 JS
1. 历史和发展
JavaScript
的定位
JavaScript
是一种属于网络的脚本语言, 已经被广泛用于 Web 应用开发
,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。
JavaScript
是脚本编程语言JavaScript
是弱类型语言JavaScript
是动态类型的JavaScript
是单线程的JavaScript
解释型语言JavaScript
具有良好的跨平台性
JavaScript
和ECMAScript
的区别,以及和DOM
、BOM
的关系,
ECMAScript
是脚本语言JavaScript
的标准化规范
;
-
1994 年
,Netscape
(网景)公司发布了Navigator
浏览器 1.0 版本,市场占用率超过 90% -
1995年12月
,升阳与网景联合发表了JavaScript
。 -
1996年11月
,网景公司将JavaScript
提交给欧洲计算机制造商协会进行标准化。 -
1997年6月
,ECMA-262
的第一个版本被Ecma
组织采纳。ECMAScript
是ECMA-262
标准化的脚本语言的名称。 -
最初命名为
Mocha
,后来改名为LiveScript
,最后重命名为JavaScript
。
ECMAscript
由于只是语法的标准, 所以在很多地方也都有了实现甚至超越了浏览器本身的存在.
-
ECMAscript
在浏览器中的实现JavaScript
-
ECMAscript
在flash
中的实现ActionScript
-
ECMAscript
在服务器端的实现Nodejs
JavaScript
包含
DOM
(文档对象模型),提供了与网页内容交互的方法
和接口
BOM
(浏览器对象模型),提供了与浏览器交互的方法
和接口
ECMAScript
描述了JavaScript
的语法和基本对象 (核心)
ECMAScript
的版本
ES5
也称为 ECMAScript 2009
,是ECMAScript
的第5版, 是现在浏览前兼容性较好的一个版本
-
1996 年 11 月
网景公司将JS
提交给ECMA
(国际标准化组织)成为国际标准,用于对抗微软。由
ECMA
的第 39 号技术专家委员会(Technical Committee 39,简称TC39
)负责制订ECMAScript
标准,成员包括Microsoft
、Mozilla
、Google
等大公司。 -
1997 年
,ECMA
发布ECMA-262 标准
,推出浏览器标准语言ECMAScript 1.0
-
…
-
2009 年
,ECMAScript 5.0
发布 -
2011 年
,ECMAScript5.1
发布,成为ISO
国际标准,从而推动所有浏览器都支持 -
…
-
2015 年
,ECMAScript6
发布,更名为 ECMAScript 2015。 -
2016 年
,ECMAScript7
发布,ECMAScript2016
-
2017 年
,ECMAScript8
发布,ECMAScript2017
-
2018 年
,ECMAScript9
发布,ECMAScript2018
-
2019 年
,ECMAScript10
,ECMAScript2019
-
2020 年
,ECMAScript11
,ECMAScript2020
-
…
从 2015
年开始 tc39
委员会决定每年发布新的 ECMAScript
版本
ECMAScript 6
是什么
ECMAScript 6
又叫ES2015
,简称ES6
ES6
是继ES4、ES5
之后的JS 语言规范
ES6
中增加了一些新的特性ES6
的目标,是使得JavaScript
语言可以用来编写复杂的大型应用程序,成为企业级开发语言- 2015年6月发布
为什么要学习
ES6
- 提供了更加方便的新语法弥补 JS 语言本身的缺陷
- 给内置对象增加了更多的方法方便
- 新的前端项目中大量使用
ES6
的新语法 ES6
让JS
可以开发复杂的大型项目,成为企业级开发语言
ES6
兼容性
ES6
虽好,但是有兼容性问题,IE7-IE11
基本不支持ES6
- 在最新的现代浏览器、移动端、
Node.js
中都支持ES6
JavaScript
和java
的关系
首先在在概念和设计方面,Java
和 JavaScript
是两种完全不同的语言。
JavaScript
语言最初出现在Netscape Navigator 2浏览器
中。当时它叫**LiveScript
**。
然而,由于当时Java
技术如日中天,Netscape
公司觉得改为JavaScript
这个名字会更吸引人注目, 所以就是这么草率, 没有什么特殊的关系
使用场景
- 浏览器网页端开发
- 做为服务器后台语言使用
Node.js
) - 移动端手机
APP
开发,如Facebook
的React Native
、uniapp
、PhoneGap
、IONIC
- 跨平台的桌面应用程序,如使用
electronjs
ECMA5
增加
-
严格模式(
use strict
) -
提供了
json
序列化方法JSON.parse
、JSON.stringify
-
Object
对象新增了方法// 添加或更改对象属性 Object.defineProperty(object, property, descriptor) // 添加或更改多个对象属性 Object.defineProperties(object, descriptors) // 访问属性 Object.getOwnPropertyDescriptor(object, property) // 以数组返回所有属性 Object.getOwnPropertyNames(object) // 以数组返回所有可枚举的属性 Object.keys(object) // 访问原型 Object.getPrototypeOf(object) // 阻止向对象添加属性 Object.preventExtensions(object) // 如果可将属性添加到对象,则返回 true Object.isExtensible(object) // 防止更改对象属性(而不是值) Object.seal(object) // 如果对象被密封,则返回 true Object.isSealed(object) // 防止对对象进行任何更改 Object.freeze(object) // 如果对象被冻结,则返回 true Object.isFrozen(object)
-
数组新增了一些方法
Array.prototype.indexOf Array.prototype.every Array.prototype.some Array.prototype.filter Array.prototype.map Array.prototype.forEach
-
函数增加了
.bind
方法
ECMA6
- 类
- 模块化
- 箭头函数
- 函数参数默认值
- 模板字符串
- 解构赋值
- 延展操作符
- 对象属性简写
Promise
Let
与Const
ECMA7
- 数组
includes
方法,用于判断是否包含某个值 a ** b
指数运算符,它与Math.pow(a, b)
相同
ECMA8
-
async/await
-
Object.values()
-
Object.entries()
-
padStart()
和padEnd()
,填充字符串达到当前长度 -
函数参数列表结尾允许逗号
-
Object.getOwnPropertyDescriptors()
-
ShareArrayBuffer
和Atomics
对象,用于从共享内存位置读取和写入
ECMA9
-
异步迭代
-
Promise.finally()
-
Rest/Spread
属性 -
正则表达式命名捕获组(
Regular Expression Named Capture Groups
) -
正则表达式反向断言(
lookbehind
) -
正则表达式
dotAll
模式 -
正则表达式
Unicode
转义 -
非转义序列的模板字符串
ECMA10
-
更加友好的
JSON.stringify
-
新增了
Array
的flat()
方法和flatMap()
方法 -
新增了
String
的trimStart()
方法和trimEnd()
方法 -
Object.fromEntries()
-
Symbol.prototype.description
-
String.prototype.matchAll
-
Function.prototype.toString()
现在返回精确字符,包括空格和注释 -
简化
try {} catch {}
,修改catch
绑定 -
新的基本数据类型
BigInt
-
globalThis
-
import()
-
Legacy RegEx
-
私有的实例方法和访问器
ECMA11
String.prototype.matchAll
用于字符串批量匹配正则, 返回一个 可迭代对象- 类的私有属性 #字段
Promise.allSettled
不管参数中的promise
是fulfilled
还是rejected
,都会等参数中的实例都返回结果,包装实例才会结束。- 可选链操作符 使用"
?
"可选链式操作符, 会自动检测 ? 前面的对象是否存; 存在 则调用 , 不存在 则为undefined
- 动态
import
导入 bigInt
用于大数值运算
ECMA12
- 新的逻辑操作符
??
String.prototype.replaceAll
有了这个API
,替换字符不用写正则了Promise.any()
返回第一个fullfilled
的promise
,若全部reject
,则返回一个带有失败原因的AggregateError
WeakRefs
使用弱引用对象,该弱引用不会阻止 GC,并且可以在 GC 前使用WeakRef.prototype.deref ( )
解除该引用
2. 基础使用
运行流程
所有内容需要在特定的环境中运行,就像 .PSD 文件
需要在类似 PS
的软件处理一样。
浏览器内置了处理的 JS解析器
,但不同浏览器的性能不同,所以 JS
一般都在浏览器中执行,当然也有可以在服务器后台执行的 JS 解析器
。
在浏览器中访问一个网站的大概过程
- 浏览器向后台服务器(任何一个托管的服务器上, 可以是
阿里云
,腾讯云
等平台)发送请求 - 服务器返回文件快速下载到本地(
js文件
,html文件
,css文件
), 由浏览器渲染出页面 - 监听用户事件, 内存空间保存数据
- 关闭页面, 生命周期结束, 并释放占用的资源
语法规范,
;
的使用
使用分号表示一段指令的结束
- 推荐每个指令都以分号结束
- 在使用构建工具时,不使用分号结束可能会造成异常
但是 ;
确实是可以不加的, 有些时候我们确实会看到不加 ;
的代码
注释
在编程语言中基本都有注释的存在, 没必要行行都加, 在一些很难想得通的地方加就好
单行注释: 用于对一行的内容进行注释操作.
// 嗷呜, 这是注释
多行注释: 一次对连续的多行进行注释操作
/* 嗷呜, 这是注释 嗷呜, 这是注释 嗷呜, 这是注释 水代码 */
在JS
中多行注释禁止嵌套使用,因为多行注释的开头符号/*
是查找最近的*/
作为结束的, 所以多行注释嵌套会出错的!
JavaScript
是脚本语言, 所以是可以和HTML
进行混编的一种语言,使用通常也都是混入HTML
中进行的.
HTML
中使用script
标签引入JS文件或者代码.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script> // 在这里写代码 </script>
<script src = "tools.js"></script>
</head>
<body>
<button onclick="alert('不推荐, 也别这么玩')">别闹</button>
<script> // 也可以在这里写代码 </script>
<script> // 可以有多个 script 标签 </script>
</body>
</html>
script
标签的属性
属性 | 属性值 |
---|---|
src |
用于引入JS文件的地址 |
language |
用于设置脚本的类型 (废弃) |
type |
用于设置引入文件的MIME类型 |
charset |
用于设置引入文件的字符集类型 |
defer |
延时执行属性, 可以是JS 加载完毕后执行, 只对外部文件有效 |
async |
异步加载属性, 可以改变JS 文件的下载顺序, 但是不改变执行顺序 |
script
标签的三中使用方式
- 外链式
<script src = "tools.js"></script>
- 嵌入式
<script> console.log('hello ximingx'); </script>
嵌入式中使用外链式, 会忽视嵌入式代码
- 内联式
<button onclick="alert('不推荐, 也别这么玩')"></button>
避免延迟,
script
的位置要求
js
放在 <head>
标签中要等到 js
加载并解析后才会显示<body>
标签中的内容。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ximingx</title>
<script> alert('ximingx'); </script>
</head>
<body>
<h1>ximingx</h1>
</body>
页面中不会先渲染出 <h1>ximingx</h1>
, 而是文件加载并解析后, 弹出框结束后渲染出 ximingx
内容
为了解决上面的问题,可以将 js 文件
放在 标签前如下所示
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ximingx</title>
</head>
<body>
<h1>ximingx</h1>
<!-- 在页面显示后,开始对 js 的操作 -->
<script src="ximingx.js"></script>
</body>
这样的使用方式可以提高用户的体验感
三种输出方式
JavaScript
中内置有一些调试代码时的工具
- 控制台输出
console.log()
console.log('hello ximingx');
- 弹窗输出
alert()
alert('hello ximingx');
- 文档输出
document.write()
document.write('hello ximingx');
二: 基础语法
1. 变量常量
JS
中的变量是弱类型可以保存所有类型的数据,即变量没有固定的类型
变量就是可以变化的量, 是内存中可以存储数据内容的代号, 一个变量名, 对应一个存储的地址, 存放数据
与常量不同, 常量必须在声明的时候赋予一个值, 且不能更改
1. 基础知识
变量的命名规则
- 由
字母
,数字
,下划线
,$
组成, 但是不可以用数字开头 - 变量名严格区分大小写
变量名
不能和系统的保留字
,关键字
冲突
JS
关键字
break、delete、if、this、while、case、do、in、throw、with、catch、else、instanceof、try、continue、finally、new、typeof、for、return
JS
保留字
abstract、double、goto、native、static、boolean、enum、implements、package、super、byte、char、class、const、public
总结: 平常 JS
见不到的, 但是在 java
中有的, 谨慎使用它作为变量名, 之后一部分我们可以在 TS
中看到
驼峰命名法
骆驼式命名法(Camel-Case)
,是电脑程式编写时的一套命名规则。
是指混合使用大小写字母来构成变量和函数的名字, 第一个单词以小写字母开始, 第二个单词的首字母大写, 以此类推
也是一般情况下 JS
的命名规范
let userName = 'ximingx'
变量的声明的三种方式
- 声明并同时赋值
var a = "a";
- 声明但不赋值
var a;
- 没有声明, 直接使用 (唔, 有弊端,劝你别用,会被别人骂屎一样的代码)
a = "a"
使用
,
可以同时声明多个变量
let n = 2,f = 3;
弱类型
在 JS
中变量类型由所引用的值决定, 而不是定义时它的类型决定的, 和别的语言有所区别, 不需要标识类型
var web = "ximingx";
console.log(typeof web); //string
web = 99;
console.log(typeof web); //number
web = {
};
console.log(typeof web); //object
2. var let const
声明变量的三种关键字
var
let
const
变量提升
在使用 var
时会有变量提升的缺陷
var web = 'baidu.com';
console.log(web);
var class = 'class';
// 此时程序控制台的第一行不会显示 baidu.com 而是会直接报错
// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
console.log(website); // undefined
var website = 'ximingx.com'
上面是变量提升的演示
解析器会先解析代码,然后把声明的变量的声明提升到最前,这就叫做变量提升
当遇到声明 class
为变量名以后, 直接报错, 后面的代码不执行
console.log(a); // undefined
var a = 1;
console.log(a); // 1
//以上代码解析器执行过程如下
var a;
console.log(a); // undefined
a = 1;
console.log(a); // 1
下面是 if(false)
中定义的 var
也会发生变量提升
var web = "ximingx";
function ximingx() {
if (false) {
// 不执行, 仍然会发生变量提升
var web = "ximingx";
}
console.log(web);
// undefined
}
ximingx();
所以推荐 var
声明的变量, 先声明后使用
而 let
和 const
解决了这个问题
重复声明
使用
var
可能造成不小心定义了同名变量
重复声明会进行覆盖操作
//优惠价
var price = 90;
//商品价格
var price = 100;
console.log(`商品优惠价格是:${
price}`);
使用let
可以避免上面的问题,因为 let
声明后的变量不允许在同一作用域中重新声明
let web = 'ximingx.com';
let web = 'ximingx'; //Identifier 'web' has already been declared
不同作用域可以重新声明
let web = 'ximingx.com';
if (true) {
let web = 'ximingx'; //Identifier 'web' has already been declared
}
但可以改变值这是与 const
不同点
let price = 90;
price = 88;
console.log(`商品价格是:${
price}`);
使用
var
声明的变量存在于最近的函数或全局作用域中没有块级作用域的机制
没有块作用域很容易污染全局,下面函数中的变量污染了全局环境
function run() {
// 没有声明直接使用, 污染到了全局
web = "ximingx";
}
run();
console.log(web); //ximingx
没有块作用作用域时 var
也会污染全局
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // 10
使用let
有块作用域时则不会有全局污染的问题
let i = 100;
for (let i = 0; i < 6; i++) {
console.log(i);
}
console.log(i); // 100
var
全局声明的变量也存在于window
对象中,
let
与const
则不会
var a = "ximingx";
console.log(window.a); //ximingx
let
全局声明的变量不存在于 window
对象中, 不会更改 window对象
let a = "ximingx";
console.log(window.a); //undefined
所以 var
声明的变量可能会覆盖 global
中原有的变量
与
var
声明的区别是let/const
拥有块作用域
let
存在块作用域特性,变量只在块域中有效
if (true) {
let web = 'ximingx',url = 'ximingx.com';
console.log(web); //ximingx
}
console.log(web); //web is not defined
每一层都是独立作用域,里层作用域可以声明外层作用域同名变量,但不会改变外层变量
<