第十九章 大纲及浏览器处理机制(细节)

150 阅读7分钟

一、(似大纲)JS核心部分 【基础知识、底层管理、项目中如何应用】

1、数据类型 & 内存处理

  • 有哪些类型
  • 各个类型的详细解读
  • 检测数据类型
  • 数据类型之间的转换
  • 堆栈内存 & 垃圾回收机制
  • 作用域 & 闭包
  • 对象、数组、正则、Date、Math...等对象的用法
  • ...

2、面向对象

  • 对象、实例和类之间的关系
  • new
  • prototype & proto
  • this问题
  • ...

3、DOM操作 【弱化】

  • 获取关于DOM以及节点的增删改查方法
  • 盒子模型(13个属性)
  • DOM事件
    • DOM0 & DOM2 事件绑定
    • 事件对象
    • 事件传播机制
    • 事件委托
    • 拖拽
    • ...
  • 浏览器(DOM)渲染的底层操作【DOM操作的性能优化】
  • ...

4、定时器和事件循环机制

  • 定时器的玩法
  • reguesAnimationFrame
  • 同步异步的底层处理逻辑
  • Promsie及其源码
  • async/await
  • 迭代器和生成器
  • ...

5、HTTP网络通信 & Ajax前后端数据交互

  • HTTP网络相关知识
  • Ajax、fatch、axios...
  • 非同源策略请求
  • 前端性能的优化方案
  • ...

6、ECMAScript2015(ES6)& HTML5

  • 基础:let/const/class、箭头函数、解构赋值、模板字符串、数组和对象新增的方法...
  • ES6Moudule模块规范【单例、AMD、CMD、CommonJS、ES6Moudule】
  • 进阶:Promise(saync/awite)、Generator、Iterator、Reflear、Fetch...
  • Hiestory API
  • canvas
  • 音视频的处理
  • ...

7、实战思想和设计模式

8、如何学习

  • 前期:70%记忆+30%理解
  • 后期:30%记忆+70%理解

1)基础知识非常重要,我们需要做出完整的较完美的思维导图

  • 做笔记 并且定期梳理
  • 每周抽出定期的时间把笔记从头到尾过一遍

2)实战项目如何学习(切忌思维懒惰)

老师讲完案例后:

  • 自己去每一行加注释(达到中文编程的地步)
  • 第一遍(听明白):注释&参照老师的代码写一遍(不会赶紧问)
  • 第二遍(自己写出来):关闭老师代码,自己按照注释去写,哪块写不出来证明那块基础知识不扎实
  • 第三遍...直至写出来注释删掉,开始裸写
  • 直至自己能写出
  • 间隔两三天,在写一回
  1. 费曼学习法
  • 教别人

9、学习态度

1)汤之盘铭曰:苟日新、又日新、日日新。

2) IT行业 一定要有”求索“之心

3)学习没有技巧:唯一的技巧就是努力付出

二、

1、复习

JS中的数据类型

  • 原始值类型【基本数据类型/值类型】
    • Number 数字
    • string 字符串
    • boolean 布尔
    • null 空
    • undefined 未定义
    • Symbol 唯一值【ES6新增】
    • Bigint 大数 【ES6新增】
  • 对象类型
    • 标准普通对象:例如:{}
    • 标准特殊对象(对象类型的实例):例如:
      • new Array 数组
      • new Regexp 正则
      • Math 数字函数对象
      • new Date 日期对象
      • new Error 错误对象
      • Set/Map 【ES6新增的数据结构】
    • 非标准特殊对象(原始值对应的‘对象类型’的实例):例如:new Number(1)
    • 函数对象:function

2、创建一个数字(装箱&拆箱):

  • 字面量(创建的是 原始值) :var num = 10;
  • 构造函数(创建出来的是非标准特殊对象):var num2 = new Number(10);

num1 vs num2

    • 一个是原始值,一个是对象
    • num2是Number类的一个实例,可以直接调用Number.prototype上的方法
    • 从严格意义上讲:num1不是Number类上的实例(因为实例都是对象类型的)按理来说应该是无法调用Number.prototype上的方法的,但是在实际应用中是可以调用的,所以也可以称num1为Number的实例(由此引出‘装箱’&‘拆箱’知识点):
      • 浏览器在执行这段代码num1.toFixed(2)时会转化到-->new Number(num1) 默认会把原始值转换为对象,然后再去调用toFixed的方法,我们会把这种操作(把原始值转化为实例对象的过程)称之为“装箱”!!
      • num2+10--> 浏览器会默认把实例对象转换为对应的原始值,然后在进行数学运算,这个过程称之为“拆箱”
    • 装箱方法:new Number(num) || Object(num)
    • 装箱操作:new只能给Number/String/Boolean使用
      Object都可以但是null/undefined会返回空对象,Symbol会返回对象
    • 拆箱:把对象转化为原始值
      • 首先嗲用对象的“Symbol.toPrimitive”函数
      • 如果对象不具备这个属性,则调用“对象.valueOf()”这个属性,看获取的是不是原始值,是原始值则实现目标
      • 如果不是原始值,则继续调用“对象.toString()”函数,把其转化为字符串
      • 如果最后的目的是变为数字,则再把字符串转化为数字
        例如:
var num2 = new Number(10);
console.log(num2+10)
num2[Symbol.toPrimitive] ->undefined
num2.valueOf() ->10
10+10=>20

3、零碎知识汇总

  • 成员访问:obj.xxx
  • parentInt/parentFloat
    作用:都是用来把其他值转换为数字的
    查找过程:从字符串(不是字符串的,也要先转换为字符串)左侧第一个字符开始查找,把找到大的有效数字转换为数字,遇到一个非有效的,则停止查找!一个都找不到,结果是NaN!
  • NaN 不等于任何数
  • “+”在JS中比较特殊:除了数字运算,还有字符串拼接\
    • 加号两边有一边是字符串就一定是字符串拼接\
    • 加号两边有一边是对象,则可能会字符串拼接([10]+10)
  • /i++/++i/--i/i-- 肯定是数学运算(不论i是啥类型的值,都要首先转化为数字)
    /i=i+1/i+=1 不一定是数学运算,还有可能是字符串拼接**
    **+val 把val转化为数字
  • “==”连接情况
    对象==字符串 (对象转换为字符串)
    对象==对象 (比较的是内存地址)
    null==undefined (null、undefined除了互相相等和本身、与别的值都不相等)
    NaN != NaN
    其余情况只要是类型不一致,就是转数字
    布尔==字符串 都转换为数字

4、浏览器处理机制细节

  • 虚拟内存:内存条
    物理内存:硬盘
    堆栈内存都是从虚拟内存分配出来的空间
  • 打开页面时浏览器操作
    • 开辟堆栈内存
    • 堆内存中默认开辟了一个空间GO
    • 存储浏览器内置的API
    • 创建全局上下文EC(G)并进栈执行
    • VO(G)存储全局上下文中声明的对象
    • 默认创建一个全局变量window,指向GO全局对象,所以基于window.xx就可以访问内置API
  • 变量提升:
    当前上下文中,执行代码前,首先会把带“var/function”关键字的进行提前声明或者定义\
    • var 只声明
    • function 声明加定义 全局上下文中,基于var/function声明的变量,不会存储到VO(G)中,而是存储到GO(window)中,但是基于let/const声明的变量,直接存储到VO(G)中!
  • let xxx =xxxx 排除变量提升的优先顺序
    1、先创建值
    • 原始值直接存储到栈内存中
    • 对象类型存储到堆中,在把16进制的内存地址赋值给变量 2、再声明变量 3、让变量和值关联(赋值、定义)
  • 函数创建
    1、开辟堆内存空间(16进制地址)
    2、储存三部分内容
    • 声明其作用域(在哪个上下文创建的那么其作用域就是谁)
    • 存储函数体中的代码(按照字符串存储)
    • 和普通对象一样,存储键值对
    • name 函数名
    • length 形参个数
    • prototype
    • proto 3、把空间地址赋值给函数名(变量名)
  • 函数执行
    1、开辟一个全新的私有执行上下文并进栈执行
    • EC(?)
    • AO(?) 私有变量对象:存储当前上下文中声明的私有变量的 2、代码执行前处理的事情
    • 初始化作用域链<函数私有上下文,函数作用域>
    • 初始化this指向
    • 初始化arguments
    • 形参赋值(形参是私有变量)
    • 变量提升 3、代码执行
      4、私有上下文的释放问题

练习

场景:一个变量取不同值问题

/* 
        解决方案一:利用“==”会进行数据类型转换,再利用对象转数字要经过四步,此时我们重写其中某一步,拿到自己想要的值即可
        var a = [1,2,3];
        a.toString = a.shift;
        if(a==1&&a==2&&a==3){
            console.log('ok');
        }

        方案二、
        var i=0
        //数据劫持
        Object.defineProperty(window,'a',{
            get(){
                return ++i;
            }
        })
        */

        /* for (var i = 0; i < 5; i++) {
            (function (i){
                setTimeout(function () {
                    console.log(i);
                }, (i + 1) * 1000)
            })(i)
        }
         */
        /* 
        //利用let 原理依旧是闭包,利用循环中的let可以产生“私有块级上下文”也是创建5个闭包,分别保存i的值,给对应的定时器
            + 先产生一个父级私有块级上下文,用来控制循环的
            + 
        for(let i = 0;i<5;i++){
            
            setTimeout(() => {
                    console.log(index);
                }, (i + 1) * 1000)
        } 
        


        */
        /* // 定时器支持第三个及以后的参数:定时器到时间,把函数执行,会把后边的参数值,传递给这个函数
        // + 原理还是闭包:只不过是用的定时器内部大的闭包处理机制

        for (var i = 0; i < 5; i++) {
            setTimeout(function (x) {
                console.log(x);
            }, (i + 1) * 1000, i)
        } */