JS&TS(选摘版)|青训营笔记

109 阅读5分钟

JS

浏览器的进程与线程

9bff93b546cf24227333f65db5a5153.png

js在浏览器的编译过程

d4d809f1447738136290f3e7afa4f45.png

6d1444bf6e308138ab9a9c9208b8e57.png 绝大多数编译器以预先编译(AOT)或实时编译(JIT)形式工作。

  • 使用命令行或者集成开发环境(IDE)调用预先编译(AOT)的编译器,如 gcc
  • 实时编译器通常是用来提高性能的,令你没有感知的,如 V8

V8 引入了即时编译(JIT)双轮驱动的设计(混合使用编译器和解释器的技术),这是一种权衡策略,给 JavaScript 的执行速度带来了极大的提升。

垃圾回收

02a17a2413076dcf734ab218dc4213f.png

老生代:

标记清除

  • 遍历所有的对象找活动对象做标记
  • 遍历所有的对象清除没有标记的对象
  • 回收相应空间

缺点

  1. 清除过之后留下的是碎片空间而不是连续空间,还需再要移动
  2. 效率低、费时【js在做垃圾回收时js本身是停顿的】 解决办法可以是标记清除是断续的,清除一个之后执行js,再进行下一个清除,再执行...

优点

相对于引用计数算法来说:解决对象循环引用的不能回收问题。

计数清除

  • 当某一个对象的引用关系发生改变时,引用计数器就会自动的修改这个对象所对应的引用数值,引用数值为0的时候开始工作,将当前的对象空间回收

优点

发现计数为0即回收,减少卡顿时间

缺点

  1. 无法回收循环引用的对象【可能会出现内存泄漏】
  2. 时间开销大【时刻监控当前引用数值是否修改,修改需要时间】

新生代:

在新生代当中,V8将内存分为两个相等的空间,分别为From空间和To空间。当From空间被占满的时候,V8会将Form空间中存活对象复制到To空间,并且将Form空间进行清空,然后将From空间和To空间交换,这样就完成了一次垃圾回收。

注:新生代中没有被清除的碎片最后会放到老生代进行清除

TS

语法

let 变量:类型=值

function fn(参数:类型,参数:类型):类型{}

数据类型

  • 字面量:

    • let a:10;【将a声明为数字类型,并且确定是10,后续不能更改a=11
    • let b:"male"|true`联合类型`:表示字符串“male”或者是布尔“true”】
      
  • any:

    • 表示任意类型,相当于对ts关闭了类型检测【显式】
    • let a;声明变量不指定类型,也相当于是any【隐式】
  • unknown:

       let a:any;
       let b:string;
       b=a【相当于把any类型赋给b了,自己不安全还霍霍了别人】
    
    • unknown相对安全,不能把自己赋值给别人
    • 可以用as做类型断言,b=a as string;就不会报错了

    类型断言语法:

    <类型>变量|变量 as 类型

  • viod:

    • 表示为空,以函数为例表示没有返回值【表示return null|return undefined】
  • never:

    • 表示永远不会返回结果【throw error,立即结束,函数不返回】
  • object&array

e008482ab705e7b216553c27853e196.png

072b2d19c671de2ba0d03f158b65b06.png

  • tuple:

    • 固定长度的数组 let a:[number,string,........]按元素顺序声明类型
  • enum:

    enum Gender{male=0;female=1}
    let a:{name:string,gender:Gerder}
    i={
        name :"李"
        gender:Gender.female//1
    }
    
  • 类型别名

类型别名可以简化类型的使用,不能重复声明

   type myType=1|2|3|4|5;//给类型取个别名
   let a:myType;//直接引用别名就相当于声明类型了
   let b:myType;

基本写法:

  • 直接定义的属性是实例属性,需要通过new出来的实例去访问

  • 加上static关键字的属性是类属性,需要通过类本身去访问

  • 【可读,可写,加上readonly就不能改了】

class Person{
    name:string="li"
    static age:number=3
    constructor(height:number){//每次创建实例时都会调用这个构造函数,通过不同实例访问传参添加属性
        this.height=height
    }
}
const per=new Person()
console.log(per.name,Person.age)

const per1=new Person(180)

继承:

class Person{
    name:string
    age:number
    constructor(height:number){
        this.height=height
    }
    sayHi(){
        console.log("Hi~~~~")
    }
}

class Worker extends Person{

    //1.继承之后添加方法
    doIt(){
        console.log(`${this.height}完成项目一`)
    }
    
    //2.只在子类中修改方法【方法的重写,也是覆盖】
    sayHi(){
        console.log("打工人/(ㄒoㄒ)/~~")
    }
    
    //3.添加属性
    gender:string
    constructor(height:number,gender:string){//添加属性后为了让实例访问到,必须重写构造函数
        super(height)//必须把父类的构造函数通过super继承过来
        this.gender=gender
    }
}
const work1=new Worker(158)
work1.doIt()//158完成项目一
work1.sayHi()//打工人打工人/(ㄒoㄒ)/~~
const work2=new Worker(168,"male")
console.log(work2)//Worker {name: undefined, age:  undefined, height: 168, gender: 'male'}

抽象类:

  • 当不希望父类被用来创建实例时,添加abstract,称作抽象类

  • 抽象类里面可以添加抽象方法,子类必须对抽象方法进行重写

abstract class Pets{
       name:string;
       age:number;
   
       constructor(name:string,age:number){
           this.name=name;
           this.age=age ;
       };
       //抽象类中可以添加抽象方法,没有方法体
       abstract sayhello():void;//子类必须对抽象方法进行重写
   }

属性的封装:

用属性修饰符来设置属性:

  • public:可以在任意位置访问修改
  • private:只能在类内部进行访问修改,若想修改可以通过get、set方法对属性进行设置;继承的子类也不能访问
  • protect:【折中】只能在当前类和当前类的子类中使用,不能通过实例访问

接口

接口用来定义一个类结构,说明一个类里面应该包含哪些属性和方法;可以当作类型声明去使用

interface myInterface{
    name:string;
    age:number;
}

const obj:myInterface={
    name:"sss",
    age:111
}

interface myInterface{//可以重复声明,实现接口时需满足并集
    gender:string
}
  • 接口中所有的属性都不能有实际的值,只定义对象结构,不考虑实际值,里面所有方法都必须是抽象方法
interface myInter{
    name:string;
    sayHello():void;
}
class Myclass implements myInter{
    name:string
    constructor(name:string){
        this.name=name
    }
    sayHello(){
        console.log("hello~~~")
    }
}

泛型

在定义函数或是类时,如果遇到类型不明确就可以使用泛型。优点是比any更安全,因为any≠any

基础用法:

//一:基础使用
function fn<T>(a:T):T{
    return a
}
fn(a:10)//1.ts对类型进行检查,调用时推断为number
fn<string>(a:"li")//2.调用时指定类型

//二:可以同时指定多个
function func<T,K>(a:T,b:K):T{}

//三:使用接口
interface Inter{
    length:number
}
function fun<T extends Inter>(a:T):number{
    return a.length
}
fun(a:"hello")//传进来的参数必须有接口的length属性

基础操作符

335286980a0de98affbc9bf35c93095.png

f5a7333958f258eac84a32281c8acfb.png

基础操作符&接口&泛型的案例

3282bbf4022182fc9244e4beeb35203.png

声明文件

1fc8990b13a3d61b0421cc68422773a.png