zoukankan      html  css  js  c++  java
  • JS高级

    * 基本(值)类型
      * Number ----- 任意数值 -------- typeof   
      * String ----- 任意字符串 ------ typeof
      * Boolean ---- true/false ----- typeof
      * undefined --- undefined ----- typeof/===
      * null -------- null ---------- ===
    * 对象(引用)类型
      * Object ----- typeof/instanceof   存储数据
      * Array ------ instanceof         属性为数字下标,内部数据是有序的
      * Function ---- typeof  存储代码,并执行
    instanceof:判断对象的具体类型,不是字符串类型
     typeof判断出来的是数值类型的字符串表达,判断出来显示的是小写的字符串,不能判断null和object,object和array,都返回object不能区别开
    1. undefined与null的区别?
      * undefined代表定义未赋值
      * nulll定义并赋值了, 只是值为null
    2. 什么时候给变量赋值为null呢?
      * 初始赋值, 表明将要赋值为对象
      * 结束前, 让对象成为垃圾对象(被垃圾回收器回收)
    3. 严格区别变量类型与数据类型?(未懂)
      * 数据的类型
        * 基本类型
        * 对象类型
      * 变量的类型(变量内存值的类型)
        *  基本类型: 保存就是基本类型的数据
        * 引用类型: 保存的是地址值
    数据 变量 内存
    1. 什么是数据?
      * 存储在内存中代表特定信息的'东东', 本质上是0101...
      * 数据的特点: 可传递, 可运算
      * 一切皆数据
      * 内存中所有操作的目标: 数据
        * 算术运算
        * 逻辑运算
        * 赋值
        * 运行函数
    2. 什么是内存?
      * 内存条通电后产生的可储存数据的空间(临时的)
      * 内存产生和死亡: 内存条(电路版)==>通电==>产生内存空间==>存储数据==>处理数据==>断电==>内存空间和数据都消失
      * 一块小内存的2个数据
         * 内部存储的数据
         * 地址值
      * 内存分类
        * 栈: 全局变量/局部变量
        * 堆: 对象
    3. 什么是变量?
      * 可变化的量, 由变量名和变量值组成
      * 每个变量都对应的一块小内存, 变量名用来查找对应的内存, 变量值就是内存中保存的数据
    4. 内存,数据, 变量三者之间的关系
      * 内存用来存储数据的空间
      * 变量是内存的标识
     
    关于引用变量赋值问题
      * 2个引用变量指向同一个对象, 通过一个变量修改对象内部数据, 另一个变量看到的是修改之后的数据
      var obj1 = {name: 'Tom'}
      var obj2 = obj1
      obj2.age = 12       //修改对象内部数据
      console.log(obj1.age)  // 12
      * 2个引用变量指向同一个对象, 让其中一个引用变量指向另一个对象, 另一引用变量依然指向前一个对象
      var a = {age: 12}
      var b = a
      a = {name: 'BOB', age: 13}  //指向另一个对象
      b.age = 14
      console.log(b.age, a.name, a.age) // 14 Bob 13
      function fn2 (obj) {
        obj = {age: 15}           //给obj换了个地址值,没有修改a,当函数用完则成为垃圾对象(形参只在函数作用域内起效果)
      }()
      fn2(a)
    
      console.log(a.age)   //13
    问题: 在js调用函数时传递变量参数时, 是值传递还是引用传递
      * 理解1: 都是值(基本/地址值)传递
      * 理解2: 可能是值传递, 也可能是引用传递(地址值)
    问题: JS引擎如何管理内存?
    1. 内存生命周期
      * 分配小内存空间, 得到它的使用权
      * 存储数据, 可以反复进行操作
      * 释放小内存空间
    2. 释放内存
      * 局部变量: 函数执行完自动释放
      * 对象: 成为垃圾对象==>垃圾回收器回收
     
    对象
    1. 什么是对象?
      * 多个数据的封装体
      * 用来保存多个数据的容器
      * 一个对象代表现实中的一个事物
    2. 为什么要用对象?
      * 统一管理多个数据
    3. 对象的组成
      * 属性: 属性名(字符串)和属性值(任意)组成
      * 方法: 一种特别的属性(属性值是函数)
    4. 如何访问对象内部数据?
      * .属性名: 编码简单, 有时不能用(包含特殊字符 - 空格 变量名不确定)
      * ['属性名']: 编码麻烦, 能通用
     
    函数
    4. 如何调用(执行)函数?
      * test(): 直接调用
      * obj.test(): 通过对象调用
      * new test(): new调用
      * test.call/apply(obj): 临时让test成为obj的方法进行调用
      var obj = {}
      function test2 () {
        this.xxx = 'atguigu'
      }
      // obj.test2()  不能直接, 根本就没有
      test2.call(obj) // obj.test2()   // 可以让一个函数成为指定任意对象的方法进行调用
      console.log(obj.xxx)

    回调函数

    1. 什么函数才是回调函数?
      1). 你定义的
      2). 你没有调
      3). 但最终它执行了(在某个时刻或某个条件下)
    2. 常见的回调函数?
      * dom事件回调函数 ==>发生事件的dom元素
      * 定时器回调函数 ===>window

      * ajax请求回调函数(后面讲)
      * 生命周期回调函数(后面讲)

     匿名函数自调用(立即调用函数)

    2. 作用
      * 隐藏实现
      * 不会污染外部(全局)命名空间
      * 用它来编码js模块

     this的指向

    1. this是什么?
      * 任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window
      * 所有函数内部都有一个变量this
      * 它的值是调用函数的当前对象
    2. 如何确定this的值?
      * test(): window
      * p.test(): p
      * new test(): 新创建的对象
      * p.call(obj): obj
     
    显示原型与隐式原型
    * 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个空Object对象
      * 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值
    * 程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前)
     
    原型链(不懂)
    1. 原型链(图解)
      * 访问一个对象的属性时,
        * 先在自身属性中查找,找到返回
        * 如果没有, 再沿着__proto__这条链向上查找, 找到返回
        * 如果最终没找到, 返回undefined
      * 别名: 隐式原型链
      * 作用: 查找对象的属性(方法)
     
    1. 函数的显示原型指向的对象默认是空Object实例对象(但Object不满足)
    2. 所有函数都是Function的实例(包含Function)
    3. Object的原型对象是原型链尽头
     
    1. 读取对象的属性值时: 会自动到原型链中查找
    2. 设置对象的属性值时: 不会查找原型链, 如果当前对象中没有此属性, 直接添加此属性并设置其值
    3. 方法一般定义在原型中, 属性一般通过构造函数定义在对象本身上
     
    作用域与执行上下文
    1. 区别1
      * 全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了。而不是在函数调用时
      * 全局执行上下文环境是在全局作用域确定之后, js代码马上执行之前创建
      * 函数执行上下文是在调用函数时, 函数体代码执行之前创建
    2. 区别2
      * 作用域是静态的, 只要函数定义好了就一直存在, 且不会再变化
      * 执行上下文是动态的, 调用函数时创建, 函数调用结束时就会自动释放
    3. 联系
      * 执行上下文(对象)是从属于所在的作用域
      * 全局上下文环境==>全局作用域
      * 函数上下文环境==>对应的函数使用域

     

    fu()的作用域没有在show()里面

     闭包:

    1. 如何产生闭包?
      * 当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时, 就产生了闭包
    2. 闭包到底是什么?
      * 使用chrome调试查看
      * 理解一: 闭包是嵌套的内部函数(绝大部分人)
      * 理解二: 包含被引用变量(函数)的对象(极少数人)
      * 注意: 闭包存在于嵌套的内部函数中
    3. 产生闭包的条件?
      * 函数嵌套
      * 内部函数引用了外部函数的数据(变量/函数)
      *执行外部函数
     
    常见的闭包
    1. 将函数作为另一个函数的返回值
    2. 将函数作为实参传递给另一个函数调用
     // 1. 将函数作为另一个函数的返回值
      function fn1() {
        var a = 2
        function fn2() {
          a++
          console.log(a)
        }
        return fn2
      }
      var f = fn1()
      f() // 3
      f() // 4
    
      // 2. 将函数作为实参传递给另一个函数调用
      function showDelay(msg, time) {
        setTimeout(function () {
          alert(msg)
        }, time)
      }
      showDelay('atguigu', 2000)

     闭包的作用:

    1. 使用函数内部的变量在函数执行完后, 仍然存活在内存中(延长了局部变量的生命周期)
    2. 让函数外部可以操作(读写)到函数内部的数据(变量/函数)

     闭包的生命周期:

    1. 产生: 在嵌套内部函数定义执行完时就产生了(不是在调用) 
    2. 死亡: 在嵌套的内部函数成为垃圾对象时  f=null,闭包死亡
    闭包的应用2 : 定义JS模块
      * 具有特定功能的js文件
      * 将所有的数据和功能都封装在一个函数内部(私有的)
      * 只向外暴露一个包含n个方法的对象或函数
      * 模块的使用者, 只需要通过模块暴露的对象调用方法来实现对应的功能
    function myModule() {
      //私有数据
      var msg = 'My atguigu'
      //操作数据的函数
      function doSomething() {
        console.log('doSomething() '+msg.toUpperCase())
      }
      function doOtherthing () {
        console.log('doOtherthing() '+msg.toLowerCase())
      }
      //向外暴露对象(给外部使用的方法)
      return {
        doSomething: doSomething,
        doOtherthing: doOtherthing           //包装成一个对象
      }
    }

    //调用
     var module = myModule()
      module.doSomething()
      module.doOtherthing()
     
    (function () {
      //私有数据
      var msg = 'My atguigu'
      //操作数据的函数
      function doSomething() {
        console.log('doSomething() '+msg.toUpperCase())
      }
      function doOtherthing () {
        console.log('doOtherthing() '+msg.toLowerCase())
      }
    
      //向外暴露对象(给外部使用的方法)
      window.myModule2 = {
        doSomething: doSomething,
        doOtherthing: doOtherthing        //将向外暴露的函数添加为window属性
      }
    })()

    //调用
      myModule2.doSomething()
      myModule2.doOtherthing()
     

    第二种更方便,因为第一种需要先执行外部函数

    1. 内存溢出
      * 一种程序运行出现的错误
      * 当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误
    2. 内存泄露
      * 占用的内存没有及时释放
      * 内存泄露积累多了就容易导致内存溢出
      * 常见的内存泄露:
        * 意外的全局变量
        * 没有及时清理的计时器或回调函数
        * 闭包
     
     var name = "The Window";
      var object = {
        name : "My Object",
        getNameFunc : function(){
          return function(){
            return this.name;
          };
        }
      };
      alert(object.getNameFunc()());  //?  the window object.getNameFunc()返回了一个函数,然后在调用函数,所以是全局调的
    
    
      //代码片段二
      var name2 = "The Window";
      var object2 = {
        name2 : "My Object",
        getNameFunc : function(){
          var that = this;
          return function(){
            return that.name2;
          };
        }
      };
      alert(object2.getNameFunc()()); //?  my object object.getNameFunc()返回一个函数,调用函数,然后that=this,这个this在object中调用

    this的情况:

    1.当以函数的形式调用时,this指向的是window

    2.当以方法的形式调用时,谁调用方法this就指向谁

    3.当以构造函数形式调用时,this就是新创建的那个对象

    原型链继承

    方式1: 原型链继承
      1. 套路
        1. 定义父类型构造函数
        2. 给父类型的原型添加方法
        3. 定义子类型的构造函数
        4. 创建父类型的对象赋值给子类型的原型 sub.prototype = new Supper(); //sub子类型 super父类型 ,这一步相当于将sub的object实例对象当作垃圾回收,地址指向supper实例对象
        5. 将子类型原型的构造属性设置为子类型 sub.prototype.constructor = sub 
        6. 给子类型原型添加方法   
        7. 创建子类型的对象: 可以调用父类型的方法
      2. 关键
        1. 子类型的原型为父类型的一个实例对象
     
    组合继承
    方式3: 原型链+借用构造函数的组合继承
    1. 利用原型链实现对父类型对象的方法继承 获取方法
    2. 利用call()借用父类型构建函数初始化相同属性  call获取属性
     
    线程机制和事件机制
    1. 进程:程序的一次执行, 它占有一片独有的内存空间
    2. 线程: CPU的基本调度单位, 是程序执行的一个完整流程
    3. 进程与线程
      * 一个进程中一般至少有一个运行的线程: 主线程
      * 一个进程中也可以同时运行多个线程, 我们会说程序是多线程运行的
      * 一个进程内的数据可以供其中的多个线程直接共享
      * 多个进程之间的数据是不能直接共享的
    4. 浏览器运行是单进程还是多进程?
      * 有的是单进程
        * firefox
        * 老版IE
      * 有的是多进程
        * chrome
        * 新版IE
    5. 如何查看浏览器是否是多进程运行的呢?
      * 任务管理器==>进程
    6. 浏览器运行是单线程还是多线程?
      * 都是多线程运行的
  • 相关阅读:
    go module基本使用
    jquery的radio的change事件
    etcd 快速入门
    linux下查看php-fpm是否开启以及如何开启
    js 获取某年的某天是第几周
    gland go list-m:无法识别的导入路径
    Xshell连接有跳板机(堡垒机)的服务器
    PHP中时间戳和时区
    SQL分页过多时, 如何优化
    MySQL语句的优化
  • 原文地址:https://www.cnblogs.com/zyq982796687/p/14725478.html
Copyright © 2011-2022 走看看