day-062-sixty-two-20230505-回顾JavaScript知识体系的综合性整理-数据类型转化-堆栈内存及闭包作用域
回顾JavaScript知识体系的综合性整理
- 数据类型和堆栈内存
- 变量声明:
- 声明方式(var、function、let、const、class、import模块)
- 命名方式
- kebab-case:连字符命名法,用于CSS样式类名 & Vue中的组件调用 如
<el-button>
- camelCase : 小驼峰命名法「用于JavaScript常规变量及属性命名…」
- PascalCase:帕斯卡命名法(或者大驼峰命名)「JavaScript类、组件名…」
- kebab-case:连字符命名法,用于CSS样式类名 & Vue中的组件调用 如
- 数据类型分类
- 基础类型
- 引用对象类型
- 数据类型检测 *****
- typeof 主用于基础数据类型
- instanceof 主要用于已知的引用数据类型
- constructor 用于已知构造函数的引用数据类型
- Object.prototype.toString.call
- 数据类型转换 ***
- 对象、函数、数组、正则、字符串、Math、Date等常用的方法和细节处理 *
- 对象常用方法
- 函数常用方法
- 数组常用方法
- 正则元字符和修饰符
- 堆栈内存
- 闭包作用域 ***
- 柯里化函数、compose函数、惰性函数 *****
- 函数的防抖和节流 *****
- 数组和对象的深浅拷贝和深浅合并 *****
- …
- 变量声明:
- 面向对象编程
- 对象、类、实例
- 三者关系
- new的原理 *****
- new与不new的区别
- 写一个new
- prototype和__proto__
- this指向的问题 ***
- 链式写法
- 类的继承、封装、多态 *****
- 插件组件封装及鸭式变形…
- …
- 对象、类、实例
- DOM操作
- 获取DOM元素/元素(节点)集合的方法
- 节点关系属性
- 节点的增删改
- 操作DOM元素的样式
- 事件绑定
- DOM0级DOM2级事件绑定
- 事件对象
- 事件的传播机制
- 事件委托(事件代理) ***
- 拖拽的处理
- …
- 异步编程&动画处理
- 定时器 和 requestAnimationFrame ***
- 动画的处理
- EventLoop事件循环机制 *****
- Promise *****
- async/await *****
- 浏览器底层沉浸机制[DOM回流重绘]
- …
- HTTP网络&Ajax前后端数据通信
- 从输入URL地址到看到整个页面,中间发生了什么(HTTP网络知识) *****
- ajax基础知识
- 核心四步操作
- GET系列请求和POST系列请求的区别
- 核心是因为传参方式
- 安全问题
- 传输内容大小的问题
- 缓存问题
- 核心是因为传参方式
- readyState状态值
- status(HTTP状态码)
- 200成功
- 无特殊处理的成功
- 301永久重定向(用于域名交替,域名服务器帮你的)、302临时转移/307临时重定向(服务器超负荷时先转移,服务器负载均衡)、304走缓存(协商缓存,浏览器自己帮你的)
- 都是经过特殊处理的错误
- 400(服务器拒绝-参数有误)、401(服务器拒绝-权限问题)、403(服务器拒绝访问-不告知原因)、404(访问地址错误)、405(请求方式不被支持,如用post去访问)、408(请求超时)
- 一般是前端的问题,换参数等
- 500(未知服务器错误–服务器那边有问题,如服务器起火)、502(网关有问题)、503(服务器超负荷–可用服务器负载均衡来处理,有人能进,有人不能进)
- HTTP状态码
- 200成功
- xhr的属性和方法及事件监听
- 查看原型,看私有属性与公有属性
- 传输数据的问题
- 客户端发请求给服务器,想要传递一些信息给服务器
- 请求头,如token等
- 问号传参,如get请求参数
- 请求主体
- 请求主体的具体格式要求
- 通过请求头的Content-Type
- 格式类型
- 字符串格式 主要用于与服务通信
- JSON字符串,最常用 ‘{“xxx”:xxx,…}’ MIME:application/json
- urlencoded字符串 ‘xxx1=xxx&xxx2=xxx…’ MIME:application/x-www-form-urlencoded
- 普通字符串 ‘…’ MIME:text/plain
- Form-Data格式 主要用于文件的上传 MIME:multipart/form-data
- Buffer或者二进制格式
- …
- 字符串格式 主要用于与服务通信
- 不支持普通对象格式,默认情况下 xhr.send({xxx:xxx,…}), 写的普通对象,会变为’[object Object]’ 传递给服务器!
- 请求主体的具体格式要求
- 服务器想把信息返回给客户端
- 响应头
- 响应主体[也有一些具体的格式]
- 字符串格式
- 一般常用的就是json字符串
- Buffer、二进制、文件流格式
- …
- 字符串格式
- 客户端发请求给服务器,想要传递一些信息给服务器
- jQuery中的$.ajax库(选学)
- 基于Promise封装的ajax库:axios
- 基础运用 axios.get/axios.post…
- 二次封装
- 通用配置
- transformRequest,请求主体处理
- 请求拦截器
- 响应拦截器
- axios的几个特点
- 会把在请求主体中写的普通对象,默认转换为JSON字符串,发送给服务器
- 会自动识别常见的数据格式,自动基于Content-Type设置对应的MIME类型
- 会自动把从服务器获取的JSON字符串转换为JSON对象(可以基于responseType配置项设置)
- fetch新一代前后端通信方案 *****
- 跨域解决方案及其原理和运用
- jsonp:原理和封装
- 偶尔用
- CORS:跨域资源共享,后端的服务器配置
- proxy:跨域代理(最常用的),前端的服务器配置
- 原理和配置
- 其它方案:postMessage、document.domain…
- jsonp:原理和封装
- …
- 一些其它的知识体系
- 设计模式: *****
- 单例模式、构造函数模式、发布订阅模式、Promise承诺者模式、观察者模式、装饰器模式…
- 插件和库:jQuery、swiper、animate.css、Bootstrap(选学)…
- ES6知识汇总
- let/const/class(和var/function区别)
- 模块规范:单例、AMD、CommonJS(CMD)、ES6Module
- 箭头函数(主要是和普通函数的区别)
- 解构赋值
...
运算符- 模块字符串
- ?.可选链 obj?.x?.y.z
- 数组和对象中新增的方法 ***
- Symbol/BigInt
- Set/Map *****
- Promise/async/await *****
- Generator/Iterator *****
- Proxy/Reflect *****
- Fetch *****
- …
- 设计模式: *****
数据类型转化
-
把其他数据类型转换为Number
-
Number([val])
- 一般用于浏览器的“隐式转换”中
- 数学运算
- isNaN检测
- ==比较
- …
- 规则:
-
字符串转换为数字:空字符串变为0,如果出现任何非有效数字字符,结果都是NaN
-
把布尔转换为数字:true->1 false->0
-
null->0 undefined->NaN
-
Symbol无法转换为数字,会报错:
Uncaught TypeError: Cannot convert a Symbol value to a number
-
BigInt去除
n
(超过安全数字的,会按照科学计数法处理) -
把对象转换为数字:
- 先调用对象的
Symbol.toPrimitive
这个方法- 如果不存在这个方法:则继续下一步处理
- 如果存在这个方法:则把这个方法执行,传递"number"标识进去
- 调用此方法可以传递’number’/‘string’/‘default’
- 再调用对象的
valueOf
获取原始值- 如果获取的值是原始值:这就是转换的结果
- 如果不是原始值,则继续下一步
- 再调用对象的
toString
把其变为字符串 - 最后再把字符串基于Number方法转换为数字
//=============================== let obj = {}; let arr = [10]; let time = new Date(); let num = new Number(10);console.log(Number(obj)); //NaN // obj[Symbol.toPrimitive] -> undefined // obj.valueOf() -> {} // obj.toString() -> '[object Object]' // Number('[object Object]') -> NaNconsole.log(Number(arr)); //10 // arr[Symbol.toPrimitive] -> undefined // arr.valueOf() -> [10] // arr.toString() -> '10' // Number('10') -> 10console.log(Number(time)); //时间戳(距离1970.1.1毫秒差) // time[Symbol.toPrimitive] -> 函数 // time[Symbol.toPrimitive]('number') 调用此方法会传递‘number’、‘string’、‘default’console.log(Number(num)); //10 // num[Symbol.toPrimitive] -> undefined // num.valueOf() -> 10
/* // 2.a等于什么值,可以让条件成立 var a = ?; if (a == 1 && a == 2 && a == 3) {console.log('OK'); } *//* 方案一:当前的比较是基于“==”来处理的,所以a的值只要不是数字类型,都会隐式转换为数字类型「Number(a)」@1 经过初步分析,a只能是一个对象 @2 把对象基于Number进行隐式转换,会经历 Symbol.toPrimitive -> valueOf -> toString -> Number@3 所以我们只要对其转换的某一步进行重写,让每一次转换分别返回 1/2/3 ,就可以实现需求了 */var a = { x: 0 }; a[Symbol.toPrimitive] = function toPrimitive() {return ++a.x; }; if (a == 1 && a == 2 && a == 3) {console.log("OK"); }/* var a = [1, 2, 3]; a.toString = a.shift; if (a == 1 && a == 2 && a == 3) { console.log('OK'); } *//* 方案二:在全局上下文中,基于var声明的变量,会放在GO中(相当于给window设置一个属性)@1 以后 a==1 ,就是获取window.a的值,和1进行比较@2 既然这样,我们就可以对window.a做数据劫持,在获取其值的时候,让每一次返回 1/2/3「GET函数」 */ var i = 0; Object.defineProperty(window, "a", {get() {return ++i;}, }); if (a == 1 && a == 2 && a == 3) {console.log("OK"); }
- 先调用对象的
-
- 一般用于浏览器的“隐式转换”中
-
parseInt([val])与parseFloat([val])
- 一般用于手动转换
- 规则:[val]值必须是一个字符串,如果不是则先转换为字符串;然后从字符串左侧第一个字符开始找,把找到的有效数字字符最后转换为数字「一个都没找到就是NaN」;遇到一个非有效数字字符,不论后面是否还有有效数字字符,都不再查找了;parseFloat可以多识别一个小数点;
-
parseInt([val],[radix])
- 从[val]左侧开始进行查找,找到所有符合[radix]进制的内容,然后把其按照[radix]进制转换为10进制!!
- [radix]是设置的进制,取值有效范围是2~36之间,如果不在有效范围内,结果就是NaN
- [radix]不写或者设置为
0
,默认就是10
- 特殊情况:如果[val]是以
0x
开始的,则默认值是16
- 特殊情况:如果[val]是以
- 从[val]左侧开始进行查找,找到所有符合[radix]进制的内容,然后把其按照[radix]进制转换为10进制!!
-
-
把其他数据类型转换为字符串
- 也分为:隐式转换和显式转换
- 显式转换
- 方法有:String([val]) 或者 [val].toString() 等
- String([val]) 和 [val].toString() 的处理机制是不一样的
- [val].toString()规则:
- 基于原型链查找机制,找私有和公有上的toString方法
- 把找到的方法执行即可!!-> 如果用的是Object.prototype.toString方法,不是用来转字符串,而是检测数据类型的!!
- String([val])规则:
- 对于其它原始值来讲,基本上就是拿字符串包起来
- 对象转字符串
- String(对象):按照 先找Symbol.toPrimitive -> 再调用valueOf -> 最后调用toString 来处理
- [val].toString()规则:
- String([val]) 和 [val].toString() 的处理机制是不一样的
- 方法有:String([val]) 或者 [val].toString() 等
- 隐式转换使用的都是String([val])这种方式
- 显式转换
+
除数学运算,还可能代表的字符串拼接-
有两边,一边是字符串,肯定是字符串拼接
-
有两边,一边是对象,则可能是字符串拼接,还有可能是数学运算
-
只出现在左边,例如:+“10” 这种方式就是把其它值转换为数字
-
遇到++i或者i++,一定是把i的值变为数字再进行累加的
-
…
let result = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false; // 100 + true + 21.2 + null -> 122.2 // 122.2 + undefined -> NaN // NaN + "Tencent" -> "NaNTencent" // 往后所有操作都是字符串拼接 "NaNTencentnull9false"
-
- 也分为:隐式转换和显式转换
-
把其他数据类型转换为Boolean
- 转换规则:除了
0/NaN/空字符串/null/undefined
五个值是false,其余都是true - 出现情况:
- Boolean([val]) 或者 !/!!
- 条件判断
- …
- 转换规则:除了
-
==
相等,两边数据类型不同,需要先转为相同类型,然后再进行比较- 对象==字符串 对象转字符串
null==undefined -> true
null
/undefined
和其他任何值都不相等null===undefined -> false
- 对象==对象 比较的是堆内存地址,地址相同则相等
- NaN!==NaN NaN和任何值(包含本身)都不相等
- 除了以上情况,只要两边类型不一致,剩下的都是转换为数字,然后再进行比较的
-
===
绝对相等,如果两边类型不同,则直接是false,不会转换数据类型「推荐」 -
Object.is([val1],[val2])
检测两个值是否相等「ES6新增的」- 核心用的是
===
- 特殊:
- Object.is(NaN,NaN) => true
- Object.is(+0,-0) => false
- 核心用的是
堆栈内存及闭包作用域
对象的堆栈内存
/* //3. 下面代码输出结果?
let obj={x:1,y:[10,20]
};
let obj2=obj;
let obj3={...obj2
};
obj2.x=100;
obj2.y[1]=30;
obj3.x=200;
obj3.y[2]=40;
obj=obj3.y={x:0,y:[1,2]
};
console.log(obj,obj2,obj3); */let obj = {x: 1, //1-->100y: [10, 20], //[10, 20]-->[10,30]-->[10,30,40]
}; //{ x: 0, y: [1, 2], }
let obj2 = {...obj,
}; //{ x: 100, y: [10,30,40], }
let obj3 = {...obj2,
}; //{x:1,y:obj.y}-->{x:200,y:obj.y}-->{x:200,y:{ x: 0, y: [1, 2], }}
obj2.x = 100;
obj2.y[1] = 30;
obj3.x = 200;
obj3.y[2] = 40;
obj = obj3.y = {x: 0,y: [1, 2],
};
console.log(obj, obj2, obj3); //{ x: 0, y: [1, 2], }//{ x: 100, y: [10,30,40], },{x:200,y:{ x: 0, y: [1, 2], }}
函数及闭包作用域
- 作用域链:遇到一个变量,要怎么查找–通过作用域链,上级上下文。
- 原型链:一个对象变量里的属性,要怎么查找,对象的原型。
/* // 4. 下面代码输出结果?
let x = 5;
function fn(x) {return function (y) {console.log(y + ++x);};
}
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x); */let x = 5;
function fn(x) {return function (y) {console.log(y + ++x);};
}
let f = fn(6); //function (y) {console.log(y + ++x);} |-|-| x=6 |-|-| x=7 |-|-| x=8
f(7); //14;
fn(8)(9); //18
f(10); //18
console.log(x); //5
进阶参考
- HTTP状态码
- ES6入门教程 – 作者:阮一峰