Web前端自学记录(十九) JS高级知识

JS高级知识

1.数据类型

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.分类
            基本()类型
                String 任意字符串
                Number 任意数字
                Boolean true/false
                Undefined undefined
                Null null
            引用类型(对象)
                Object 任意对象
                Function 一种特别的对象(可以执行)
                Array 一种特别的对象(数值下标,内部数据是有序的)
        2.判断
            typeof 返回数据类型的字符串表达 可以判断undefined 数值 字符串 布尔值 function 不能判断null与object object与array
            instanceof 判断对象的具体类型
            === 可以判断undefined,null
     -->
     <!-- 
         1.undefined与null的区别
            undefined代表定义未赋值
            null定义并赋值了,只是值为null
        2.什么时候给变量赋值为null
            初始值赋值为null,表明将要赋值为对象
            结束前赋值为null,让对象成为垃圾对象(被垃圾回收器回收)
        3.严格区分变量类型与数据类型
            数据的类型
                基本类型
                对象类型
            变量的类型(变量内存值的类型)
                基本类型:保存的就是基本类型的数据
                引用类型:保存的是地址值
      -->
     <script>
     /* 
         实例:实例对象
         类型:类型对象
     */
    function Person(name ,age) {//构造函数 类型
        this.name = name
        this.age = age
    }
    var p = new Person("tom",12)//根据类型创建的实例对象
    </script>
</body>
</html>

2.数据_变量_内存

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.什么是数据
            存储在内存中代表特定信息的"东西"。本质上是0101...
            数据的特点:可传递,可运算
            一切皆数据
            内存中所有操作的目标:数据
                算术运算
                逻辑运算
                赋值
                运行函数
        2.什么是内存
            内存条通电以后产生的可存储数据的空间(临时的)
            内存产生和死亡:内存条(电路板)==>通电==>产生内存空间==>存储数据==>处理数据==>断电==>内存空间和数据都消失
            一块小内存的2个数据
                内部存储数据
                地址值
            内存分类
                栈:全局变量/局部变量
                堆:对象
        3.什么是变量
            可变化的量,由变量名和变量值组成
            每个变量都对应一块小内存,变量名用来查找对应的内存,变量值就是内存中保存的数值数据
        4.内存,数据,变量三者之间的关系
            内存用来存储数据的空间
            变量是内存的标识
     -->
     <!-- 
         问题:var a = xxx,a内存中到底保存的是什么?
            xxx是基本数据,保存的就是这个数据
            xxx是对象,保存的是对象的地址值
            xxx是一个变量,保存的是xxx的内容(可能是基本数据,也可能是地址值)
        
         关于引用变量赋值的问题
            n个引用变量指向同一个对象,通过一个变量修改对象内部数据,其他所有变量看到的是修改之后的数据
            n个引用变量指向同一个对象,让其中一个引用变量指向另一个对象,其他引用对象仍然指向前一个对象
        
         在js调用函数时传递变量参数时,是值传递还是引用传递
            理解1:都是值(基本值/地址值)传递
            理解2:可能是值传递,也可能是引用传递(地址值)
        
         JS引擎如何管理内存
            1.内存生命周期
                分配小内存空间,得到它的使用权
                存储数据,可以反复进行操作
                释放小内存空间
            2.释放内存
                局部变量:函数执行完自动释放
                对象:成为垃圾对象==>垃圾回收器回收
      -->
</body>
</html>

3.对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.什么是对象
            多个数据的封装体
            用来保存多个数据的容器
            一个对象代表现实中的一个事物
        2.为什么要用对象
            统一管理多个数据
        3.对象的组成
            属性:属性名(字符串)和属性值(任意)组成
            方法:一种特别的属性(属性值是函数)
        4.如何访问对象的内部数据
            .属性名:编码简单,有时不能用
            ['属性名']:编码复杂,能通用
        问题:什么时候必须使用['属性名']的方式
            1.属性名包含特殊字符:- 空格
            2.属性名不确定 属性名在[]不用引号
     -->
</body>
</html>

4.函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.什么是函数
            实现特定功能的n条语句的封装体
            只有函数是可以执行的,其他类型的数据不能执行
        2.为什么要用函数?
            提高代码复用
            便于阅读交流
        3.如何定义函数?
            函数声明
            表达式
        4.如何执行/调用函数
            test():直接调用
            obj.test():通过对象调用
            new test()new调用
            test.call/apply(obj):临时让test成为obj的方法进行调用
     -->
</body>
</html>

回调函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.什么函数才是回调函数?
            1)你定义的
            2)你没有调
            3)但最终它执行了(在某个时刻或某个条件下)
        2.常见的回调函数
            dom事件回调函数==>this是发生事件的dom元素
            定时器回调函数==>this是window

            ajax请求回调函数
            生命周期回调函数
     -->
</body>
</html>

IIFE立即执行函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.理解
            全称:Immediately-Invoked Function Expression
        2.作用
            隐藏实现
            不会污染外部(全局)命名空间
            用它来编写js模块
     -->
</body>
</html>

函数中的this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.this是什么
            任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window
            所偶遇函数内部都有一个变量this
            它的值是调用函数的当前对象
        2.如何确定this的值
            test():window
            p.test():p
            new test():新创建的对象
            p.call(obj):obj
     -->
</body>
</html>

5.函数的prototype

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.函数的prototype属性()
            每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为:原型对象)
            原型对象中有一个属性constructor,它指向函数对象
        2.给原型对象添加属性(一般都是方法)
            作用:函数的所有实例对象自动拥有原型中的属性(方法)
     -->
</body>
</html>

显示原型与隐式原型

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.每个函数function都有一个prototype,即显式原型(属性)
        2.每个实例对象都有一个__proto__,可称为隐式原型(属性)
        3.对象的隐式原型的值为其构造函数的显示原型的值
        4.内存结构()
        5.总结:
            函数的prototype属性:在定义函数是自动生成,默认是一个空Object对象
            对象的__proto__属性:创建对象时自动添加的,默认值为构造函数的prototype属性值
            程序员能直接操作显式原型,但不能直接操作隐式原型(ES6之前)
     -->
</body>
</html>

原型链

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.原型链(图解)
            访问一个对象的属性时
                先在自身属性中查找,找到返回
                如果没有,再沿着__proto__这条链向上查找,找到返回
                如果最终没有找到,返回undefined
            别名:隐式原型连
            作用:查找对象的属性(方法)
        2.构造函数/原型/实体对象的关系(图解)
        3.构造函数/原型/实体对象的关系2(图解)
     -->
     <!-- 
         1.函数的显式原型指向的对象默认是空Object实例对象(但Object不满足)
         2.所有函数都是Function的实例(包含Function)
         3.Object的原型对象是原型链的尽头
      -->
</body>
</html>

原型链_属性问题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.读取对象的属性值时:会自动到原型链中查找
        2.设置对象的属性值时,不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值
        3.方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
     -->
</body>
</html>

探索instanceof

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.instanceof是如何判断的?
            表达式:A instanceof B
            如果B函数的显式原型对象在A对象的原型链上,返回true,否则返回false
        2.Function是通过new自己产生的实例
     -->
     <script>
         console.log(Object instanceof Function);//true
         console.log(Object instanceof Object);//true
         console.log(Function instanceof Function);//true
         console.log(Function instanceof Object);//true
     </script>
</body>
</html>

6.变量提升与函数提升

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.变量声明提升
            通过var定义(声明)的变量,在定义语句之前就可以访问到
            值:undefined
        2.函数声明提升
            通过function声明的函数,在之前就可以直接调用
            值:函数定义(对象)
        3.问题:变量提升和函数提升是如何产生的?
     -->
</body>
</html>

7.执行上下文

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.代码分类(位置)
            全局代码
            函数代码
        2.全局执行上下文
            在执行全局代码前将window确定为全局执行上下文
            对全局数据进行预处理
            var定义的全局变量==>undefined,添加为window的属性
            function声明的全局函数==>赋值(fun),添加为window的方法
            开始执行全局代码
        3.函数执行上下文
            在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
            对局部数据进行预处理
                形参变量==>赋值(实参)==>添加为执行上下文的属性
                arguments==>赋值(实参列表),添加为执行上下文的属性
                var定义的局部变量==>undefined,添加问执行上下文的属性
                function声明的函数==>赋值(fun),添加为执行上下文的属性
                this==>赋值(调用函数的对象)
                开始执行函数体代码
     -->
</body>
</html>

执行上下文栈

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.在全局代码执行之前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象
        2.在全局执行上下文(window)确定后,将其添加到栈中(压栈)
        3.在函数执行上下文创建后,将其添加到栈中(压栈)
        4.在当前函数执行完后,将栈顶的对象移出(出栈)
        5.当所有代码执行完后,栈中只剩下window
     -->
     <!-- 
         递归调用:在函数内部调用自己
      -->
</body>
</html>

8.作用域与作用域链

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.理解
            就是一块"地盘",一个代码段所在的区域
            它是静态的(相对于上下文对象),在编写代码时就确定了
        2.分类
            全局作用域
            函数作用域
            没有块作用域(ES6有了)
        3.作用
            隔离变量,不同作用域下同名变量不会有冲突
     -->
     <!-- 
         作用域与执行上下文
         1.区别1
            全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了,而不是在函数调用时
            全局执行上下文环境时在全局作用域确定之后,js代码马上执行前创建
            函数执行上下文环境是在调用函数时,函数体代码执行前创建
         2.区别2
            作用域是静态的,只要函数定义好的就一致存在,且不会再变化
            执行上下文是动态的,调用函数时创建,函数调用结束时上下文环境就会被自动释放
         3.联系
            执行上下文(对象)是从属于所在的作用域
            全局上下文环境==>全局作用域
            函数上下文环境==>对应的函数作用域
      -->
      <!-- 
          作用域链
          1.理解
            多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外)
            查找变量时就是沿着作用域链来查找的
          2.查找一个变量的查找规则
            在当前作用域下的执行上下文中查找对应的属性,如果有直接返回,否则进入2
            在上一级作用域的执行上下文中查找对应的属性,如果有直接返回,否则进入3
            再次执行2的相同操作,直到全局作用域,如果还找不到就抛出找不到的异常
       -->
</body>
</html>

9.闭包

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.如何产生闭包
            当一个嵌套的内部()函数引用了嵌套的外部()函数的变量(函数)时,就产生的闭包
        2.闭包到底是什么
            使用chrome调试查看
            理解一:闭包是嵌套的内部函数(绝大部分人)
            理解二:包含被引用变量(函数)的对象(很少数人)
            注意:闭包存在于嵌套的内部函数中
        3.产生闭包的条件
            函数嵌套
            内部函数引用了外部哈纳树的数据(变量/函数)
            执行函数定义就会产生闭包(不用调用内部函数)
     -->
</body>
</html>

常见的闭包

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.将函数作为另一个函数的返回值
        2.将函数作为实参传递给另一个函数调用

        闭包的作用
            1.使用函数内部的变量在函数执行完后,仍然存活在内存中(延长了局部变量的生命周期)
            2.让函数外部可以操作(读写)到函数内部的数据(变量/函数)
     -->
     <!-- 
         问题
         1.函数执行完后,函数内部声明的局部变量是否还存在? 一般是不存在,存在于闭包中的变量才可能存在
         2.在函数外部能直接访问函数内部的局部变量吗? 不能,但我们可以通过闭包让外部操作它
      -->
      <!-- 
          闭包的生命周期
            产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
            死亡:在嵌套的内部函数成为垃圾对象时
       -->
     <script>
         function fn1() {
             var a =2
             function fn2() {
                 a++
                 console.log(a);
             }
             return fn2
         }
         var f = fn1()
         f()//3
         f()//4

         function showDelay(msg,time) {
             setTimeout(function() {
                 alert(msg)
             },time)
         }
         showDelay("atguigu",2000)
     </script>
</body>
</html>

闭包的应用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        闭包的应用:定义JS模块
            具有特定功能的JS文件
            将所有的数据和功能都封装在一个函数内部(私有的)
            只向外暴露一个包含n个方法的对象或函数
            模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
     -->
</body>
</html>
function myModule(){
    // 私有的属性
    var msg = 'my atguigu'
    // 操作数据的函数
    function doSomething() {
        console.log('doSomething()'+msg.toUpperCase());
    }
    function doOtherthing() {
        console.log('doOtherthing()' +msg.toLocaleUpperCase());
    }
    // 向外暴露对象(给外部使用的方法)
    return {
        doSomething:doSomething,
        doOtherthing:doOtherthing
    }
}

(function(window){
    // 私有的属性
    var msg = 'my atguigu'
    // 操作数据的函数
    function doSomething() {
        console.log('doSomething()'+msg.toUpperCase());
    }
    function doOtherthing() {
        console.log('doOtherthing()' +msg.toLocaleUpperCase());
    }
    // 向外暴露对象(给外部使用的方法)
    window.myModule2 = {
        doSomething:doSomething,
        doOtherthing:doOtherthing
    }
})(window)

闭包的缺点及解决

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.缺点
            函数执行完后,函数内的局部变量没有释放,占用内存时间会变长
            容易造成内存泄露
        2.解决
            能不用闭包就不用
            及时释放
     -->
     <!-- 
         1.内存溢出
            一种程序运行出现的错误
            当程序运行需要的内存超过了剩余的内存时,就抛出内存溢出的错误
         2.内存泄露
            占用的内存没有及时释放
            内存泄漏积累多了就容易导致内存溢出
            常见的内存泄露:
                意外的全局变量
                没有及时清理的计时器或回调函数
                闭包
      -->
</body>
</html>

10.对象创建模式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        方式一:Object构造函数模式
            套路:先创建空Object对象,再动态添加属性/方法
            适用场景:起始时不确定对象内部数据
            问题:语句太多
        方式二:对象字面量模式
            套路:使用{}创建对象,同时指定属性/方法
            适用场景:起始时对象内部数据是确定的
            问题:如果创建多个对象,有重复代码
        方式三:工厂模式
            套路:通过工厂函数动态创建对象并返回
            适用场景:需要创建多个对象
            问题:对象没有一个具体的类型,都是Object类型
        方式四:自定义构造函数模式
            套路:自定义构造函数,通过new创建对象
            适用场景:需要创建多个类型确定的对象
            问题:每个对象都有相同的数据,浪费内存
        方式五:构造函数+原型的组合模式
            套路:自定义构造函数,属性在函数中初始化,方法添加到原型上
            适用场景:需要创建多个类型确定的对象
     -->
</body>
</html>

11.原型链的继承

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        方式1:原型链继承
            1.套路
                1.定义父类型构造函数
                2.给父类型的原型添加方法
                3.定义子类型的构造函数
                4.创建父类型的对象赋值给子类型的原型
                5.将子类型原型的构造属性设置为子类型
                6.给子类型原型添加方法
                7.创建子类型的对象:可以调用父类型的方法
            2.关键
                1.子类型的原型为父类型的一个实例对象

        方式2:借用构造函数继承(假的)
            1.套路
                1.定义父类型构造函数
                2.定义子类型构造函数
                3.在子类型构造函数中调用父类型构造函数
            2.关键
                1.在子类型构造函数中通用call()调用父类型构造函数

        方式3:原型链+借用构造函数的组合继承
            1.利用原型链实现对父类型对象的方法继承
            2.利用call()借用父类型构造函数初始化相同属性
     -->
     <script>
         function Person(name,age) {
             this.name = name
             this.age = age
         }
         Person.prototype.setName = function (name) {
             this.name = name
         }
         function Student(name,age,price) {
             Person.call(this,name,age)//为了得到属性
             this.price = price
         }
         Student.prototype = new Person()//为了能看到父类型的方法
         Student.prototype.constructor = Student//修正constructor属性
         Student.prototype.setPrice = function (price) {
             this.price = price
         }
     </script>
</body>
</html>

12.进程与线程

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        进程:
            程序的一次执行,它占有一片独有的内存空间
            可以通过windows任务管理器查看进程
        线程:
            是进程内的一个独立执行单元
            是程序执行的一个完整流程
            是CPU的最小的调度单元
        相关知识:
            应用程序必须运行在某个进程的某个线程上
            一个进程中至少有一个运行的线程:主线程,进程启动后自动创建
            一个进程中也可以同时运行多个线程,我们会说程序是多线程运行的
            一个进程内的数据可以共其中多个线程直接共享
            多个进程之间的数据是不能直接共享的
            线程池(thread pool):保存多个线程对象的容器,实现线程对象的反复利用
        相关问题
            何为多进程与多线程
                多进程:一个应用程序可以同时启动多个实例运行
                多线程:在一个进程内,同时有多个线程运行
            比较单线程与多线程
                多线程
                    优点:能有效提升CPU的利用率
                    缺点:
                        创建多线程开销
                        线程间切换开销
                        死锁与状态同步问题
                单线程
                    优点:顺序变成简单易懂
                    缺点:效率低
            JS是单线程还是多线程
                JS是单线程运行的
                但是用H5中的Web Workers可以多线程运行
            浏览器运行是单线程还是多线程
                浏览器是多线程运行的
            浏览器运行是单进程还是多进程
                有的是单进程
                    firefox
                    老版IE
                有的是多进程
                    chrome
                    新版IE
                如何查看浏览器是否是多进程运行的
     -->
</body>
</html>

13.浏览器内核

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        浏览器内核
            支撑浏览器运行的最核心的程序
            不同的浏览器可能不一样
                Chrome,Safari:webkit
                firefox:Gecko
                IE:Trident
                360,搜狗等国内浏览器:Trident+webkit
            内核由很多模块组成
                JS引擎模块:负责js程序的编译与运行
                html,css文档解析模块:负责页面文本的解析
                DOM/CSS模块:负责dom/css在内存中的相关处理
                布局和渲染模块:负责页面的布局和效果的绘制(内存中的对象)
                ......
                定时器模块:负责定时器的管理
                事件响应模块:负责事件的管理
                网络请求模块:负责ajax请求
     -->
</body>
</html>

14.定时器引发的思考

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.定时器真是定时执行的吗?
            定时器并不能保证真正定时执行
            一般会延迟一丁点(可以接受),也有可能延迟很长时间(不能接受)
        2.定时器回调函数实在分线程执行的吗?
            在主线程执行的,js是单线程的
        3.定时器是如何实现的?
            事件循环模型
     -->
</body>
</html>

15.JS是单线程执行的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.如何证明js执行是单线程的?
            setTimeout()的回调函数是在主线程执行的
            定时器回调函数只有在运行栈中的代码全部执行完后才有可能运行
        2.为什么js要用单线程模式,而不用多线程模式?
            JavaScript的单线程,与它的用途有关
            作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM
            这决定了它只能是单线程,否则会带来很复杂的同步问题
        3.代码的分类:
            初始化代码
            回调代码
        4.js引擎执行代码的基本流程
            先执行初始化代码:包含一些特别的代码 回调函数(异步执行)
                设置定时器
                绑定监听
                发送ajax请求
            后面在某个时刻才会执行回调代码
     -->
</body>
</html>

16.事件循环模型

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 
        1.所有代码分类
            初始化执行代码(同步代码):包含有dom事件监听,设置定时器,发送ajax请求的代码
            回调执行代码(异步代码):处理回调逻辑
        2.js引擎执行代码的基本流程
            初始化代码==>回调代码
        3.模型的两个重要组成部分:
            事件(定时器/DOM时间/Ajax)管理模块
            回调队列
        4.模型的运转流程
            执行初始化代码,将事件回调函数交给对应管理模块
            当事件发生时,管理模块会将回调函数及其数据添加到回调队列中
            只有当初始化代码执行完后(可能要一定时间),才会遍历读取回调队列中的回调函数执行
     -->
</body>
</html>

17.H5 Web Workers多线程

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text" placeholder="数值" id="number">
    <button id="btn">计算</button>
    <script>
        var input = document.getElementById("number")
        document.getElementById("btn").onclick = function () {
            var number = input.value
            // 创建一个worker对象
            var worker = new Worker("worker.js")
            // 绑定接收消息的监听
            worker.onmessage = function (event) {
                console.log("主线程接收分线程返回的数据"+event.data);
                alert(event.data)
            }
            // 向分线程发送消息
            worker.postMessage(number)
            console.log("主线程向分线程发送数据"+number);
        }
    </script>
    <!-- 
        1.H5规范提供了js分线程的实现,取名为:Web Workers
        2.相关API
            Worker:构造函数,加载分线程执行的js文件
            Worker.prototype.onmessage:用于接收另一个线程的回调函数
            Worker.prototype.postMessage:向另一个线程发送消息
        3.不足
            worker内代码不能操作DOM(更新UI)
            不能跨域加载JS
            不是每个浏览器都支持这个新特性
     -->
</body>
</html>
function fibanacci(n) {
    return n<=2 ? 1 : fibanacci(n-1) + fibanacci(n-2)//递归调用
}


var onmessage = function (event) {
    var number = event.data
    console.log("分线程接收到主线程发送的数据:"+number);
    // 计算
    var result = fibanacci(number)
    postMessage(result)
    console.log("分线程向主线程返回数据:"+result);

}

后续会持续更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值