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

  1. 键值对的集合 键是字符串,非字符串会强行转化为字符串,字符串相同后来者会覆盖前者

Function
JS中函数是一等公民,是可以像其他数据类型被处理
例如:

  • 被赋值给变量
  • 可以作为参数传递
  • 可以作为返回值返回
  • 可以存储在数据结构中,存在数组中
  • 可以作为对象的属性

Array
迭代器 + 原型方法

es5对象之面向对象梳理
面向对象概念:类、继承、封装、多态
es5中与面向对象对应的是:this指针、作用域、作用域链、闭包、原型、原型链
目前我的认知还是在ES5本身的特性,再加上ES6面向对象
this指针

  • 全局上下文中this指向全局对象
  • 函数上下文中this指向函数对象
  • 对象方法中this指向对象
  • dom绑定事件中this指向dom元素
  • 箭头函数中this指向当前代码声明的对象块

改变函数中的this指针

  1. 声明函数
  2. 调用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比较操作。
相等运算符 、!=、=、!==判断相等和不相等。
按位与 &位与运算。
按位异或 ^位异或运算。
按位或 |位或运算。
逻辑与 &&逻辑与运算。
逻辑或 ||逻辑或运算。
条件运算符 ? :三元运算符。
赋值运算符 =、+=、-=、
=、/= 等赋值和复合赋值运算。
逗号运算符 ,用于在表达式中包含多个操作。

posted @ 2025-03-27 18:59  张正1998  阅读(35)  评论(0)    收藏  举报