一、JavaScript基础内容
1 JavaScript简介
JavaScript包含三部分:ECMAscript(该语言的语法和基本对象)、DOM、BOM
高级语言分类:
- 编译性语言(C、C++):源码一次性全部编译成二进制文件,再执行 。 特点:需要编译 源码一次性编译
- 解释性语言(Python、JavaScript):读一行源码 执行一行源码。 特点:不需要编译 源码一行一行的执行
- java是先编译再解释 比较特殊
动/静态类型语言:
- 动态类型语言(灵活但不安全):不确定一个变量(标识符)的类型,在代码执行过程中可动态修改
1
2var name = '123'
name = 123 //可行 不会报错- 静态类型语言:在代码执行之前,可以确定一个变量(标识符)准确的类型,并且之后不允许修改
1
2let name :string = 'abc';
name = 123 //报错 因为改变了数据类型JavaScript的应用场景
- 1 网页的交互
- 2 服务端开发(Node.js)
- 3 命令行工具(Node.js)
- 4 桌面程序 vscode 就是用TypeScript开发的
- 5 APP(React Native)
- 6 游戏开发(cocos2d-js)
- 7 微信小程序开发
JavaScript文档注释 一般用于给函数作说明
1 | /** |
并行、并发、单线程
并行是指同时执行,只有多线程的语言才支持
并发本质是充分利用cpu资源(多个任务交替使用cpu),并没有正真同时执行
JavaScript、Python都是单线程语言,只能实现并发,不能实现并行
Python的多线性是通过伪线程实现的
JavaScript 并发
- 宏任务,微任务机制实现并发,EventLoop
- 本质是CPU足够快,当请求资源时(查询数据库、网络请求等),此时CPU就空出来了,而这时CPU会切换到其他任务,只要切换的足够快,就实现了并发。
Node.js 优势是只能异步编程,不支持同步编程,异步编程就大大提升了资源的利用率
2 JavaScript编码规范
变量命名规范:驼峰式
= 赋值 两边空格
变量的定义
1
2用let、const而不用var
var没有块级作用域类的定义
1
const obj = {}//大括号
数组的定义
1
const arr = []
方法的定义
1
2
3fangfa(){
}简写
1
2
3
4
5const name = 'xioaming'
const person = {
name, //简写、且在未简写属性上面
age: 18, //属性后有','
}使用箭头函数
1
2
3(res) => {
}参数写法
1
2
3
4
51 参数一个个列出来,最好不用params对象(内部参数明确)
2 用{}包裹参数,以便调用时仍然可以以对象的形式传入
request({url,data={},method='GET'}){
}
3 基础语法
3.1 for循环
forEach((item) => {}) 同步执行
for(let i in list) i取到的是list数组的索引值, i取到的是list对象的键 同步执行
for(let item of list) item取到的是list数组的元素, item取到的是list对象的值 异步执行
3.2 Object.keys()
Object.keys()
返回结果为对象直接子节点的键,数据类型为Array
1 | const json = { |
3.3 构建数组
- 构建二维数组
1 | const flow1 = Array.from({length: 数组长度}, () => new Array(数组长度).fill(数组填充内容)) |
- 字典转数组
1 | let list = Array.from(map) |
3.4 原型链上添加属性或方法
- 将方法或属性挂在数组原型链上
- 新建任何一个数组,都可以访问这个属性或方法
- 利用了原型链的特性:如果A对象上没有找到x属性(方法),那么会沿着A对象的原型链找x属性(方法)
- 这个方法可以通过this拿到实例化的数组
- 新建任何一个数组,都可以访问这个属性或方法
1 | Array.prototype.bubbleSort = function () { |
3.5 forEach()
1 | const res = [1,2,3,4,5] |
3.6 获取项目根目录地址
1 | process.cwd() |
3.7 拼接对象 Object.assign
Object.assign只能实现浅拷贝,即只能拷贝第一层,更深层的只拷贝了引用
例如下面的obj1.type和obj2.type指向的是同一个内存地址 ,修改obj1.type.a ,obj2.type.a也会被修改
1 | const obj1 = { |
3.8 对象键值对定义
1 | //正常定义 |
3.9 util内置帮助函数
1 | const util = require('util') |
3.10 判断属性不是原型上的属性
1 | for (let key in obj) { |
3.11 obj[键]式获取对象值
1 | let test = { |
3.12 对象与类区别
- 直接定义的简单对象中可以定义方法,且可以通过对象直接调用方法
- 定义的类需要实例化后才能调用方法
- 类的本质是函数
- 实例化后为对象
1 | const wangwu = { |
3.13 匿名函数
1 | //匿名函数包裹一个括号 |
- 用
!
分隔匿名函数(多个匿名函数时,不加!
会引发错误),!
不会影响代码执行
1 | !(async function () { |
3.14 ?语法
3.15 var let const
var和let const 的区别
- var 和let是变量,可修改;const是常量,不可修改;
let const 有块级作用域,var没有
var是 ES5语法,let const是ES6语法;var有变量提升
1 | // 变量提升 ES5 |
- var 和 let 在闭包中的不同
- var是函数作用域,var定义的变量在for的块之外,所以不能形成闭包
- let 是块级作用域, 在一个for的块中就会形成闭包
1 |
|
4 阅读代码提示
5 易错点
5.1 循环导入
循环导入会导致,导入的类为undefined,以下面的情况为例,a.js、b.js互相循环导入对方的模块,则报错,报错提示导入的模块为undefined
- 目录结构:
- a.js
- b.js
1
2
3
4
5//a.js
const a = require('./a.js')
//b.js
const b = require('./b.js')- 目录结构:
解决方案
- 不在文件头部导入,而是在使用的地方导入
二、ES6
0 ES6教程地址
1 块级作用域 var —> const let
- ES5之前没有块级作用域的概念(if for都没有块级作用域 但是function有块级作用域),所以很多时候必须借助function作用域解决引用块级外变量的问题
- ES6加入了let和const 都有了块级作用域
1 | //ES5 |
const使用注意事项
定义之后不能修改
在定义时 必须附初始值
定义的对象不能修改 但是对象内的属性可以修改
1
2
3
4
5
6
7
8
9//修改const 对象中的属性不报错
const config = {
api_base_url: 'http://bl.7yue.pro/v1',
appkey:'K57S1kGd4CLBz2dw'
}
config = 1 //报错
config.appkey = 2 //不报错
2 对象增强写法
- 属性的增强写法
- 函数的增强写法
1 | //ES5 |
3 字符串
3.1 标签字符串
- ES5之前字符串是 ‘ ‘ 或 “ “ 这方式字符串不支持换行
- ES6字符串用`` 这种方式支持字符串换行
3.2 模板字符串
1 | 用`${}`包裹数据或函数 |
- 数据替换
1 | let a = 123 |
- 函数替换
1 | test(){ |
3.3 字符串识别函数
- includes()
- startsWith()
- endsWith()
3.4 字符串补全函数
- padStart()
- padEnd()
4 模块化 导入导出
4.1 ES6 export import
- 使用前提: script type类型为module
1 | <script src='../text.js' type='module'></script> |
导出:export
- 逐一导出
1
2
3
4
5
6
7
8export let myName = "Tom";
export let myAge = 20;
export let myfn = function(){
return "My name is" + myName + "! I'm '" + myAge + "years old."
}
export let myClass = class myClass {
static a = "yeah!";
}- 统一导出,等同于逐一导出
1
2
3
4
5
6
7
8
9let myName = "Tom";
let myAge = 20;
let myfn = function(){
return "My name is" + myName + "! I'm '" + myAge + "years old."
}
let myClass = class myClass {
static a = "yeah!";
}
export { myName, myAge, myfn, myClass }- export default
- 在一个文件或模块中,export、import 可以有多个,export default 仅有一个。
- export default 中的 default 是对应的导出接口变量。
- 通过 export 方式导出,在导入时要加{ },export default 则不需要。
- export default 向外暴露的成员,可以使用任意变量来接收。
1
2
3
4var a = "My name is Tom!";
export default a; // 仅有一个
import b from "./xxx.js"; // 不需要加{}, 使用任意变量接收1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//导出
let myName = "Tom";
let myAge = 20;
let myfn = function(){
return "My name is" + myName + "! I'm '" + myAge + "years old."
}
let myClass = class myClass {
static a = "yeah!";
}
export default{ myName, myAge, myfn, myClass }
//导入
import xxx from './xxx.js'
//使用
xxx.myName
xxx.myAge
xxx.myfn()
xxx.myClass
导入:import
- 导入时 路径一定是相对路径
1 | 1 逐个导入 |
- as用法
1 | /*-----export [test.js]-----*/ |
4.2对比commonJS模块
使用前提:需要node.js环境解析 所以 使用前要先安装node.js
导出
1 | module.exports = {变量名,函数名,对象名} |
- 导入
1 | let {变量名,函数名,对象名} = require('../aaa.js') |
别名
- 导出
1
2
3
4
5
6
7module.exports = {
别名:原名
}
module.exports = {
db:sequelize
}- 导入
1
2
3const {原名 : 别名} = require('../../core/db')
const {sequelize : db} = require('../../core/db')
5 箭头函数–this
- 箭头函数与其函数写法对比
1 | //箭头函数 |
- 不同情况下的箭头函数写法
1 | //1 无参数 |
6 扩展运算符…
1 | ...res :展开对象,获得对象中的每一个元素 |
7 对象、数组解构
7.1 对象解构
1 | const obj = { |
7.2 数组解构
1 | const array = ['why', 'code', 'maxthon'] |
8 类 class
9 Object.keys, for in, Object.getOwnPropertyNames, Reflect.ownKeys 区别
- for in,遍历全部可枚举属性,原型属性。不包括不可枚举属性,Symbol
- Object.keys(),获取自身可枚举属性。不包括不可枚举属性,原型属性,Symbol
- Object.getOwnPropertyNames,获取自身全部属性名称,包括不可枚举属性。不包括Symbol,不包括原型
- Reflect.ownKeys,获取自身全部属性名称,包括不可枚举属性,Symbol。不包括原型(其实就是Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和)