Tintines / JavaScriptAdvance

js高级

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

js高级

函数

函数

  1. 函数也是对象
  2. 函数具备行为,可以被调用
  3. 用来减少代码量,复用,隔离变量,减少命名污染

函数分类

  1. 普通的函数
  2. 构造函数
  3. IIFE(匿名函数自调用)
  4. 回调函数(事件的回调,定时器的回调)

函数的this

  1. 理解this:
    • 关键字
    • 变量
  2. this的指向问题
    • 函数this不是函数定义的时候决定的
    • 函数this指向谁看如何调用当前的函数
  3. this指向分类
    • 函数自调用: window
    • 构造函数(new function): 当前构造函数的实例对象
    • 对象.方法(): 对象本身
    • fun.call/apply(指定的对象): 指定的对象

原型

什么是原型对象

1. 每个函数都有一个prototype属性,该属性指向的是原型对象(显示原型对象)
2. 每个实例对象身上都有一个__proto__属性,该属性指向的也是原型对象(隐式原型对象)
3. 构造函数的显示原型 === 当前构造函数实例对象的隐式原型对象
4. 原型对象的本质: 普通的Object实例

什么是原型链

1. 查找对象的属性的时候现在自身找,如果自身没有沿着__proto__找原型对象
2. 如果原型对象上还没有,继续沿着__proto__,直到找到Object的原型对象对象
3. 如果还没有找到返回undefined
4. 原型链: 沿着__proto__查找的这条链就是原型链

变量提升 & 函数提升

1. js引擎在js代码正式执行之前会做一些预解析的工作
2. 找关键字: var, function
3. 找到var以后将var后边的变量提前声明,但是不赋值 var a;
4. 找到function以后定义对应的函数,也就是说函数在预解析的时候已经定义完毕
5. 预解析: 全局预解析,局部预解析
6. 注意:
    - 全局预解析在定义函数的时候不关心函数是否被使用
    - 函数局部预解析的时候如果内部函数没有被使用就不会提前定义

执行上下文

1. 理解: 
    - 执行上下文抽象的概念,代表了代码执行的环境,包含: 执行环境,变量对象,this,作用域链
2. 流程:
    - js引擎在js代码正式执行之前会先创建一个执行环境(开发商批的地,工程队施工的环境)
    - 进入该环境以后创建一个变量对象(打地基),该对象用于收集当前环境下的: 变量,函数,函数的参数,this
        - 找关键字var ,function
    - 确认this的指向
    - 创建作用域链
3. 重点:
    - 执行上下文是动态创建的
    - 尤其是针对函数,每调用一次函数都会创建一次执行上下文

作用域

作用域理解

  • 抽象的概念
  • 用来决定代码执行的范围, 变量所属的范围
  • 作用域是代码定义的时候决定的
  • 作用域作用:
    • 隔离变量
    • 规定其之后的作用域链是什么样的,体现: [[scopes]]: 上一级作用域链

作用域链

  • 作用域链式一个数组结构
  • 该结构内保存的是一个个的变量对象
  • 作用域链什么时候创建的:在js代码正式执行之前创建的

闭包

闭包形成的条件

  • 函数嵌套
  • 内部函数引用外部函数的局部变量
  • 内部函数被使用,注意: 函数变量提升的时候如果内部函数没有被使用,在预解析的过程中不会定义内部函数

什么是闭包

  • 闭包是一个存在内部函数的引用关系
  • 该引用指向的是外部函数的局部变量对象(前提是内部函数使用了外部函数的局部变量)

闭包的作用

  • 延长外部函数变量对象的生命周期
  • 使用闭包能够间接的从函数外部访问函数内部的私有变量

闭包的优缺点

  • 优点: 延长外部函数变量对象的生命周期
  • 缺点: 延长外部函数变量对象的生命周期(占内存,如果不及时清除容易造成内存溢出,泄漏)

使用闭包的时候注意:

  • 及时清除闭包
  • 让内部的函数成为垃圾对象 ---> 内部函数身上没有指针指向

js的继承

原型链继承

1. 核心**
    - 子类的原型 成为 父类的实例
    - Child.prototype = new Parent()
2. 注意问题:
    - 以上的写法会导致子类的构造器属性丢失
3. 解决问题
    - Child.prototype.constructor = Child
    
    
     function Person(name, age) {
        this.name = name;
        this.age = age;
      }
      Person.prototype.showName = function () {
        console.log(this.name);
      }
      var person1 = new Person('kobe', 43);
      
      // 原型继承: 子类的原型 成为 父类的实例
      // Child.prototype = {constructor: Child}
      Child.prototype = new Person();
      Child.prototype.constructor = Child;
      // 定义一个child类
      function Child(name, age) {
        this.name = name;
        this.age = age;
      }
      
      var child1 = new Child('xiaoming', 18);
    
      console.log(child1);
      child1.showName();

借用构造函数继承(不是真的继承)

1. 核心**
    - 让父类的方法在子类中执行
2. 注意问题:
    - 如果父类的方法在子类中直接调用,会导致在window对象身上添加了不必要的属性
3. 解决问题:
    - 使用call || apply
    - Parent.call(子类的实例对象, 参数)
    - Parent.call(this, 参数)

组合继承

1. 核心**: 原型继承 + 借用构造函数继承

js事件循环(轮询)机制

1. js是单线程的 ---> 主线程
2. 同步任务 || 异步任务
    - 同步: 1. 阻塞的 2. 同步是没有回调的
    - 异步: 1. 非阻塞 2. 异步有回调(用来通知当前异步任务执行的结果)
3. 定时器真的准时吗?不一样
    - 特例:定时器任务的后边有运算量大的代码段
4. 事件轮询机制:
    - 1. js任务都会在js的主线程执行
    - 2. 当开启一个异步任务的时候会交给对应的管理模块去管理
    - 3. 主线程继续执行后续的任务
    - 4. 管理模块接管的对应的回调,它会在恰当的时机将对应的回调放入callback queue中
    - 5. 当主线程上的所有同步任务执行完毕会通过 ‘轮询’的方式询问callback queue是否有可执行的回调
    - 6. 假如没有会反复询问
    - 7. 假如有可执行的回调将对应的回调钩到主线程执行
 5. 开发注意事项;
    - 不要在定时器任务之后放置运算量大的代码段;

new操作符都干了哪些事情

1. 创建一个空对象
2. 将this指向该空对象
3. 执行函数
4. 将执行的结果返回

About

js高级


Languages

Language:HTML 97.1%Language:JavaScript 2.9%