JS梳理之es5梳理
es5梳理
数据类型-基本数据类型 (基础数据类型值不可变)
Undefined、Null、Boolean、Number、BigInt、String、Symbol
- Undefined:声明时的空值
- Null:引用类型的空值
- Boolean:只有两个值:true 和 false
- Number:表示数字,包括整数和浮点数
- BigInt:用于表示大于 2^53 - 1 的整数
- String:表示文本数据,由字符组成,可以用单引号、双引号或反引号包围
- Symbol:用于创建唯一的标识符,通常用于对象属性的关键字
判断数据类型typeof操作符
// 基本数据类型示例
let a; // Undefined
console.log(typeof a); // "undefined"
let b = null; // Null
console.log(typeof b); // "object" (历史遗留问题)
let isTrue = true; // Boolean
console.log(typeof isTrue); // "boolean"
let num = 42; // Number
console.log(typeof num); // "number"
let bigInt = 12345678901234567890n; // BigInt
console.log(typeof bigInt); // "bigint"
let str = "Hello"; // String
console.log(typeof str); // "string"
let sym = Symbol('description'); // Symbol
console.log(typeof sym); // "symbol"
// 引用数据类型示例
let obj = { name: "Alice" }; // Object
console.log(typeof obj); // "object"
let arr = [1, 2, 3]; // Array
console.log(typeof arr); // "object" (数组也是对象)
function myFunction() {} // Function
console.log(typeof myFunction); // "function"
数据类型-引用数据类型(引用数据类型)
Object、Array、Function
let obj = {};
let arr = [1, 2, 3];
let func = function() {};
console.log(typeof obj); // "object"
console.log(Array.isArray(arr)); // true
console.log(arr instanceof Array); // true
console.log(obj instanceof Object); // true
console.log(func instanceof Function); // true
es5对象-梳理
Object
- 键值对的集合 键是字符串,非字符串会强行转化为字符串,字符串相同后来者会覆盖前者
Function
JS中函数是一等公民,是可以像其他数据类型被处理
例如:
- 被赋值给变量
- 可以作为参数传递
- 可以作为返回值返回
- 可以存储在数据结构中,存在数组中
- 可以作为对象的属性
Array
迭代器 + 原型方法
es5对象之面向对象梳理
面向对象概念:类、继承、封装、多态
es5中与面向对象对应的是:this指针、作用域、作用域链、闭包、原型、原型链
目前我的认知还是在ES5本身的特性,再加上ES6面向对象
this指针
- 全局上下文中this指向全局对象
- 函数上下文中this指向函数对象
- 对象方法中this指向对象
- dom绑定事件中this指向dom元素
- 箭头函数中this指向当前代码声明的对象块
改变函数中的this指针
- 声明函数
- 调用Function原型方法 call bind apply call apply会立即执行 bind会返回一个新函数
JS作用域、作用域链、闭包
作用域:ES5中是函数作用域,函数调用时即产生一个作用域,初始为全局作用域
作用域链:变量在当前函数中找不到对应的变量,会向上查找,内-》外
闭包:允许函数访问其外部作用域的变量,并保持状态
闭包与正常变量对比
函数中正常的函数变量,再执行完之后会被销毁
但是JS提供了闭包,允许JS执行完函数之后,还保留状态,它与传统的声明变量不同之处在于封闭,你从外面是没有办法访问到这个闭包变量的
// 闭包示例
function createCounter() {
let count = 0; // 私有变量
return {
increment: function() {
count++;
return count;
},
decrement: function() {
count--;
return count;
},
getCount: function() {
return count;
}
};
}
const counter = createCounter();
console.log(counter.increment()); // 输出: 1
console.log(counter.increment()); // 输出: 2
console.log(counter.decrement()); // 输出: 1
console.log(counter.getCount()); // 输出: 1
闭包导致的内存泄漏 仅限IE IE内存销毁会看你有没有被引用,IE中的dom操作相关流程会被视为引用内存即不会释放
function closure(){
// div用完之后一直存在内存中,无法被回收
var div = document.getElementById('div');
div.onclick = function () {
console.log(div.innerHTML);// 这里用oDiv导致内存泄露
};
}
// 解除引用避免内存泄露
function closure(){
var div = document.getElementById('div');
var test = div.innerHTML;
div.onclick = function () {
console.log(test);
};
div = null;
}
bind手写
//bind 正常调用
const obj = { name : 'charles' }
function test(){
console.log(this.name)
}
const func = test.bind(obj)
func();
//bind手写
//bind手写思路 返回一个函数,函数执行时的执行函数本身的改变了this的版本
Function.prototype.myBind = function (thisObj, ...args) {
const func = this
return function(){
func.apply(thisObj, ...args)
}
}
函数这一块,es5底层封装的比较死,比较抽象,你想通过打印怎么怎么样都做不到。
但是对象原型原型链这一块就不一样了,他每一步都能打印,数据比较多,一多就容易乱,所以做一个梳理。
es5中对象new对象实例、原型、原型链
对象声明方式:字面量表示法、new
new手写,new做了几件事情 它创建了一个对象示例,对象的原型是这个函数
// new常见用法就是创建一个类型的实例,
const a = new Date()
console.log(a instanceof Date) // true
// 相关概念
// new操作符接引用类型 调用引用类型的构造函数constructor 新建一个对象 内存中初始化一个空间 进行一些操作 并返回这个对象
// 这个对象的特点 独立的存储空间、能够调用引用类型中prototype的方法
myNew (Func,...args) {
const obj = {}
obj.__proto__ = Func.prototype
// 现在不在提倡__proto__ js做封装 推荐使用Object.setPrototypeOf
Object.setPrototypeOf(obj, Func.prototype);
const result = Func.constructor.call(obj,...args)
return (typeof result === 'object' && result !== null) ? result : obj;
}
原型链梳理
原型链本质上是一个查找规则,new一个实例,这个实例可以调用引用类型的prototype方法
function Person () {
}
Person.prototype.test = function(){console.log('1234')}
const per = new Person()
per.test()
// 这里可以看出 function 这个关键字 会new一个Function实例
// Person的__proto__指向了Function
// Function的__proto__指向了Object
// Object的__proto__指向了Null
// 现在推荐使用Object.getPrototypeOf()
// 然后是模拟原型链查找
function traverse(obj) {
let p1 = obj
let p2 = Object.getPrototypeOf(obj)
while(p2!==null){
p1 = p2
p2 = Object.getPrototypeOf(p2)
}
}
es5异步梳理
异步的核心内容 在于回调函数的写法,底层浏览器多线程,宏任务微任务模型 先执行完宏任务队列当前单元 在进行微任务 在进行下一个宏任务单元
1. 回调函数 宏任务嵌套 回调炼狱 书写不方便
// 回调地狱
firstTask(() => {
secondTask(() => {
thirdTask(() => {
console.log("所有任务完成");
});
});
});
2. Promise.then的链式调用
firstTask()
.then(secondTask)
.then(thirdTask)
.then(() => {
console.log("所有任务完成");
});
3. async await 同步写法
async function executeTasks() {
await firstTask();
await secondTask();
await thirdTask();
console.log("所有任务完成");
}
executeTasks();
补充内容 操作符
括号 ()用于改变默认优先级。
成员访问 . 和 数组索引 []访问对象属性或数组元素。
自增/自减 ++ 和 --(前缀)先增加或减少,再使用值。
一元运算符 +、-、!、~、typeof、void、delete对单个操作数进行操作。
乘法/除法/取余 、/、%进行乘法、除法和取余运算。
加法/减法 +、-进行加法和减法运算。
位移 <<、>>、>>>位移运算。
关系运算符 <、<=、>、>=、instanceof、in比较操作。
相等运算符 、!=、=、!==判断相等和不相等。
按位与 &位与运算。
按位异或 ^位异或运算。
按位或 |位或运算。
逻辑与 &&逻辑与运算。
逻辑或 ||逻辑或运算。
条件运算符 ? :三元运算符。
赋值运算符 =、+=、-=、=、/= 等赋值和复合赋值运算。
逗号运算符 ,用于在表达式中包含多个操作。

浙公网安备 33010602011771号